-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Revert "Revert "Revert "[clang][UBSan] Add implicit conversion check for bitfields""" #87562
Conversation
…for bitf…" This reverts commit 8a5a1b7.
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang Author: Vitaly Buka (vitalybuka) ChangesReverts llvm/llvm-project#87529 https://lab.llvm.org/buildbot/#/builders/37/builds/33262 is still broken Patch is 43.32 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/87562.diff 11 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e4c0e49ed6fc1c..8fc925350849cd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -198,10 +198,6 @@ Non-comprehensive list of changes in this release
New Compiler Flags
------------------
-- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
- sign change.
-- ``-fsanitize=implicit-integer-conversion`` a group that replaces the previous
- group ``-fsanitize=implicit-conversion``.
- ``-Wmissing-designated-field-initializers``, grouped under ``-Wmissing-field-initializers``.
This diagnostic can be disabled to make ``-Wmissing-field-initializers`` behave
@@ -215,9 +211,6 @@ Modified Compiler Flags
- Added a new diagnostic flag ``-Wreturn-mismatch`` which is grouped under
``-Wreturn-type``, and moved some of the diagnostics previously controlled by
``-Wreturn-type`` under this new flag. Fixes #GH72116.
-- ``-fsanitize=implicit-conversion`` is now a group for both
- ``-fsanitize=implicit-integer-conversion`` and
- ``-fsanitize=implicit-bitfield-conversion``.
- Added ``-Wcast-function-type-mismatch`` under the ``-Wcast-function-type``
warning group. Moved the diagnostic previously controlled by
diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst
index 531d56e313826c..8f58c92bd2a163 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.rst
+++ b/clang/docs/UndefinedBehaviorSanitizer.rst
@@ -148,11 +148,6 @@ Available checks are:
Issues caught by this sanitizer are not undefined behavior,
but are often unintentional.
- ``-fsanitize=integer-divide-by-zero``: Integer division by zero.
- - ``-fsanitize=implicit-bitfield-conversion``: Implicit conversion from
- integer of larger bit width to smaller bitfield, if that results in data
- loss. This includes unsigned/signed truncations and sign changes, similarly
- to how the ``-fsanitize=implicit-integer-conversion`` group works, but
- explicitly for bitfields.
- ``-fsanitize=nonnull-attribute``: Passing null pointer as a function
parameter which is declared to never be null.
- ``-fsanitize=null``: Use of a null pointer or creation of a null
@@ -198,8 +193,8 @@ Available checks are:
signed division overflow (``INT_MIN/-1``). Note that checks are still
added even when ``-fwrapv`` is enabled. This sanitizer does not check for
lossy implicit conversions performed before the computation (see
- ``-fsanitize=implicit-integer-conversion``). Both of these two issues are handled
- by ``-fsanitize=implicit-integer-conversion`` group of checks.
+ ``-fsanitize=implicit-conversion``). Both of these two issues are handled
+ by ``-fsanitize=implicit-conversion`` group of checks.
- ``-fsanitize=unreachable``: If control flow reaches an unreachable
program point.
- ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflow, where
@@ -207,7 +202,7 @@ Available checks are:
type. Unlike signed integer overflow, this is not undefined behavior, but
it is often unintentional. This sanitizer does not check for lossy implicit
conversions performed before such a computation
- (see ``-fsanitize=implicit-integer-conversion``).
+ (see ``-fsanitize=implicit-conversion``).
- ``-fsanitize=vla-bound``: A variable-length array whose bound
does not evaluate to a positive value.
- ``-fsanitize=vptr``: Use of an object whose vptr indicates that it is of
@@ -229,15 +224,11 @@ You can also use the following check groups:
- ``-fsanitize=implicit-integer-arithmetic-value-change``: Catches implicit
conversions that change the arithmetic value of the integer. Enables
``implicit-signed-integer-truncation`` and ``implicit-integer-sign-change``.
- - ``-fsanitize=implicit-integer-conversion``: Checks for suspicious
- behavior of implicit integer conversions. Enables
+ - ``-fsanitize=implicit-conversion``: Checks for suspicious
+ behavior of implicit conversions. Enables
``implicit-unsigned-integer-truncation``,
``implicit-signed-integer-truncation``, and
``implicit-integer-sign-change``.
- - ``-fsanitize=implicit-conversion``: Checks for suspicious
- behavior of implicit conversions. Enables
- ``implicit-integer-conversion``, and
- ``implicit-bitfield-conversion``.
- ``-fsanitize=integer``: Checks for undefined or suspicious integer
behavior (e.g. unsigned integer overflow).
Enables ``signed-integer-overflow``, ``unsigned-integer-overflow``,
diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def
index b228ffd07ee745..c2137e3f61f645 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -163,24 +163,24 @@ SANITIZER_GROUP("implicit-integer-arithmetic-value-change",
ImplicitIntegerArithmeticValueChange,
ImplicitIntegerSignChange | ImplicitSignedIntegerTruncation)
-SANITIZER_GROUP("implicit-integer-conversion", ImplicitIntegerConversion,
- ImplicitIntegerArithmeticValueChange |
- ImplicitUnsignedIntegerTruncation)
+SANITIZER("objc-cast", ObjCCast)
-// Implicit bitfield sanitizers
-SANITIZER("implicit-bitfield-conversion", ImplicitBitfieldConversion)
+// FIXME:
+//SANITIZER_GROUP("implicit-integer-conversion", ImplicitIntegerConversion,
+// ImplicitIntegerArithmeticValueChange |
+// ImplicitUnsignedIntegerTruncation)
+//SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
+// ImplicitIntegerConversion)
SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
- ImplicitIntegerConversion |
- ImplicitBitfieldConversion)
+ ImplicitIntegerArithmeticValueChange |
+ ImplicitUnsignedIntegerTruncation)
SANITIZER_GROUP("integer", Integer,
- ImplicitIntegerConversion | IntegerDivideByZero | Shift |
+ ImplicitConversion | IntegerDivideByZero | Shift |
SignedIntegerOverflow | UnsignedIntegerOverflow |
UnsignedShiftBase)
-SANITIZER("objc-cast", ObjCCast)
-
SANITIZER("local-bounds", LocalBounds)
SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 0c7f48fe00603d..54432353e7420d 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5580,44 +5580,11 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
break;
}
- // TODO: Can we de-duplicate this code with the corresponding code in
- // CGExprScalar, similar to the way EmitCompoundAssignmentLValue works?
- RValue RV;
- llvm::Value *Previous = nullptr;
- QualType SrcType = E->getRHS()->getType();
- // Check if LHS is a bitfield, if RHS contains an implicit cast expression
- // we want to extract that value and potentially (if the bitfield sanitizer
- // is enabled) use it to check for an implicit conversion.
- if (E->getLHS()->refersToBitField()) {
- llvm::Value *RHS =
- EmitWithOriginalRHSBitfieldAssignment(E, Previous, &SrcType);
- RV = RValue::get(RHS);
- } else
- RV = EmitAnyExpr(E->getRHS());
-
+ RValue RV = EmitAnyExpr(E->getRHS());
LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store);
-
if (RV.isScalar())
EmitNullabilityCheck(LV, RV.getScalarVal(), E->getExprLoc());
-
- if (LV.isBitField()) {
- llvm::Value *Result = nullptr;
- // If bitfield sanitizers are enabled we want to use the result
- // to check whether a truncation or sign change has occurred.
- if (SanOpts.has(SanitizerKind::ImplicitBitfieldConversion))
- EmitStoreThroughBitfieldLValue(RV, LV, &Result);
- else
- EmitStoreThroughBitfieldLValue(RV, LV);
-
- // If the expression contained an implicit conversion, make sure
- // to use the value before the scalar conversion.
- llvm::Value *Src = Previous ? Previous : RV.getScalarVal();
- QualType DstType = E->getLHS()->getType();
- EmitBitfieldConversionCheck(Src, SrcType, Result, DstType,
- LV.getBitFieldInfo(), E->getExprLoc());
- } else
- EmitStoreThroughLValue(RV, LV);
-
+ EmitStoreThroughLValue(RV, LV);
if (getLangOpts().OpenMP)
CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(*this,
E->getLHS());
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index a4ab8a11b867fa..397b4977acc3e9 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -15,7 +15,6 @@
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CGOpenMPRuntime.h"
-#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
@@ -309,7 +308,6 @@ class ScalarExprEmitter
llvm::Type *DstTy, SourceLocation Loc);
/// Known implicit conversion check kinds.
- /// This is used for bitfield conversion checks as well.
/// Keep in sync with the enum of the same name in ubsan_handlers.h
enum ImplicitConversionCheckKind : unsigned char {
ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7.
@@ -1105,21 +1103,6 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
{Src, Dst});
}
-static llvm::Value *EmitIsNegativeTestHelper(Value *V, QualType VType,
- const char *Name,
- CGBuilderTy &Builder) {
- bool VSigned = VType->isSignedIntegerOrEnumerationType();
- llvm::Type *VTy = V->getType();
- if (!VSigned) {
- // If the value is unsigned, then it is never negative.
- return llvm::ConstantInt::getFalse(VTy->getContext());
- }
- llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
- return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
- llvm::Twine(Name) + "." + V->getName() +
- ".negativitycheck");
-}
-
// Should be called within CodeGenFunction::SanitizerScope RAII scope.
// Returns 'i1 false' when the conversion Src -> Dst changed the sign.
static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
@@ -1144,12 +1127,30 @@ EmitIntegerSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst,
assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) &&
"either the widths should be different, or the signednesses.");
+ // NOTE: zero value is considered to be non-negative.
+ auto EmitIsNegativeTest = [&Builder](Value *V, QualType VType,
+ const char *Name) -> Value * {
+ // Is this value a signed type?
+ bool VSigned = VType->isSignedIntegerOrEnumerationType();
+ llvm::Type *VTy = V->getType();
+ if (!VSigned) {
+ // If the value is unsigned, then it is never negative.
+ // FIXME: can we encounter non-scalar VTy here?
+ return llvm::ConstantInt::getFalse(VTy->getContext());
+ }
+ // Get the zero of the same type with which we will be comparing.
+ llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
+ // %V.isnegative = icmp slt %V, 0
+ // I.e is %V *strictly* less than zero, does it have negative value?
+ return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
+ llvm::Twine(Name) + "." + V->getName() +
+ ".negativitycheck");
+ };
+
// 1. Was the old Value negative?
- llvm::Value *SrcIsNegative =
- EmitIsNegativeTestHelper(Src, SrcType, "src", Builder);
+ llvm::Value *SrcIsNegative = EmitIsNegativeTest(Src, SrcType, "src");
// 2. Is the new Value negative?
- llvm::Value *DstIsNegative =
- EmitIsNegativeTestHelper(Dst, DstType, "dst", Builder);
+ llvm::Value *DstIsNegative = EmitIsNegativeTest(Dst, DstType, "dst");
// 3. Now, was the 'negativity status' preserved during the conversion?
// NOTE: conversion from negative to zero is considered to change the sign.
// (We want to get 'false' when the conversion changed the sign)
@@ -1244,136 +1245,6 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
{Src, Dst});
}
-// Should be called within CodeGenFunction::SanitizerScope RAII scope.
-// Returns 'i1 false' when the truncation Src -> Dst was lossy.
-static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
- std::pair<llvm::Value *, SanitizerMask>>
-EmitBitfieldTruncationCheckHelper(Value *Src, QualType SrcType, Value *Dst,
- QualType DstType, CGBuilderTy &Builder) {
- bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
- bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
-
- ScalarExprEmitter::ImplicitConversionCheckKind Kind;
- if (!SrcSigned && !DstSigned)
- Kind = ScalarExprEmitter::ICCK_UnsignedIntegerTruncation;
- else
- Kind = ScalarExprEmitter::ICCK_SignedIntegerTruncation;
-
- llvm::Value *Check = nullptr;
- // 1. Extend the truncated value back to the same width as the Src.
- Check = Builder.CreateIntCast(Dst, Src->getType(), DstSigned, "bf.anyext");
- // 2. Equality-compare with the original source value
- Check = Builder.CreateICmpEQ(Check, Src, "bf.truncheck");
- // If the comparison result is 'i1 false', then the truncation was lossy.
-
- return std::make_pair(
- Kind, std::make_pair(Check, SanitizerKind::ImplicitBitfieldConversion));
-}
-
-// Should be called within CodeGenFunction::SanitizerScope RAII scope.
-// Returns 'i1 false' when the conversion Src -> Dst changed the sign.
-static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
- std::pair<llvm::Value *, SanitizerMask>>
-EmitBitfieldSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst,
- QualType DstType, CGBuilderTy &Builder) {
- // 1. Was the old Value negative?
- llvm::Value *SrcIsNegative =
- EmitIsNegativeTestHelper(Src, SrcType, "bf.src", Builder);
- // 2. Is the new Value negative?
- llvm::Value *DstIsNegative =
- EmitIsNegativeTestHelper(Dst, DstType, "bf.dst", Builder);
- // 3. Now, was the 'negativity status' preserved during the conversion?
- // NOTE: conversion from negative to zero is considered to change the sign.
- // (We want to get 'false' when the conversion changed the sign)
- // So we should just equality-compare the negativity statuses.
- llvm::Value *Check = nullptr;
- Check =
- Builder.CreateICmpEQ(SrcIsNegative, DstIsNegative, "bf.signchangecheck");
- // If the comparison result is 'false', then the conversion changed the sign.
- return std::make_pair(
- ScalarExprEmitter::ICCK_IntegerSignChange,
- std::make_pair(Check, SanitizerKind::ImplicitBitfieldConversion));
-}
-
-void CodeGenFunction::EmitBitfieldConversionCheck(Value *Src, QualType SrcType,
- Value *Dst, QualType DstType,
- const CGBitFieldInfo &Info,
- SourceLocation Loc) {
-
- if (!SanOpts.has(SanitizerKind::ImplicitBitfieldConversion))
- return;
-
- // We only care about int->int conversions here.
- // We ignore conversions to/from pointer and/or bool.
- if (!PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(SrcType,
- DstType))
- return;
-
- if (DstType->isBooleanType() || SrcType->isBooleanType())
- return;
-
- // This should be truncation of integral types.
- assert(isa<llvm::IntegerType>(Src->getType()) &&
- isa<llvm::IntegerType>(Dst->getType()) && "non-integer llvm type");
-
- // TODO: Calculate src width to avoid emitting code
- // for unecessary cases.
- unsigned SrcBits = ConvertType(SrcType)->getScalarSizeInBits();
- unsigned DstBits = Info.Size;
-
- bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
- bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
-
- CodeGenFunction::SanitizerScope SanScope(this);
-
- std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
- std::pair<llvm::Value *, SanitizerMask>>
- Check;
-
- // Truncation
- bool EmitTruncation = DstBits < SrcBits;
- // If Dst is signed and Src unsigned, we want to be more specific
- // about the CheckKind we emit, in this case we want to emit
- // ICCK_SignedIntegerTruncationOrSignChange.
- bool EmitTruncationFromUnsignedToSigned =
- EmitTruncation && DstSigned && !SrcSigned;
- // Sign change
- bool SameTypeSameSize = SrcSigned == DstSigned && SrcBits == DstBits;
- bool BothUnsigned = !SrcSigned && !DstSigned;
- bool LargerSigned = (DstBits > SrcBits) && DstSigned;
- // We can avoid emitting sign change checks in some obvious cases
- // 1. If Src and Dst have the same signedness and size
- // 2. If both are unsigned sign check is unecessary!
- // 3. If Dst is signed and bigger than Src, either
- // sign-extension or zero-extension will make sure
- // the sign remains.
- bool EmitSignChange = !SameTypeSameSize && !BothUnsigned && !LargerSigned;
-
- if (EmitTruncation)
- Check =
- EmitBitfieldTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
- else if (EmitSignChange) {
- assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) &&
- "either the widths should be different, or the signednesses.");
- Check =
- EmitBitfieldSignChangeCheckHelper(Src, SrcType, Dst, DstType, Builder);
- } else
- return;
-
- ScalarExprEmitter::ImplicitConversionCheckKind CheckKind = Check.first;
- if (EmitTruncationFromUnsignedToSigned)
- CheckKind = ScalarExprEmitter::ICCK_SignedIntegerTruncationOrSignChange;
-
- llvm::Constant *StaticArgs[] = {
- EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(SrcType),
- EmitCheckTypeDescriptor(DstType),
- llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind),
- llvm::ConstantInt::get(Builder.getInt32Ty(), Info.Size)};
-
- EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs,
- {Src, Dst});
-}
-
Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
QualType DstType, llvm::Type *SrcTy,
llvm::Type *DstTy,
@@ -2749,8 +2620,6 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::PHINode *atomicPHI = nullptr;
llvm::Value *value;
llvm::Value *input;
- llvm::Value *Previous = nullptr;
- QualType SrcType = E->getType();
int amount = (isInc ? 1 : -1);
bool isSubtraction = !isInc;
@@ -2839,8 +2708,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
"base or promoted) will be signed, or the bitwidths will match.");
}
if (CGF.SanOpts.hasOneOf(
- SanitizerKind::ImplicitIntegerArithmeticValueChange |
- SanitizerKind::ImplicitBitfieldConversion) &&
+ SanitizerKind::ImplicitIntegerArithmeticValueChange) &&
canPerformLossyDemotionCheck) {
// While `x += 1` (for `x` with width less than int) is modeled as
// promotion+arithmetics+demotion, and we can catch lossy demotion with
@@ -2851,26 +2719,13 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
// the increment/decrement in the wider type, and finally
// perform the demotion. This will catch lossy demotions.
- // We have a special case for bitfields defined using all the bits of the
- // type. In this case we need to do the same trick as for the integer
- // sanitizer checks, i.e., promotion -> increment/decrement -> demotion.
-
value = EmitScalarConversion(value, type, promotedType, E->getExprLoc());
Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
// Do pass non-default ScalarConversionOpts so tha...
[truncated]
|
Reverts #87529
Reverts #87518
https://lab.llvm.org/buildbot/#/builders/37/builds/33262 is still broken