https://github.com/anthonyhatran created https://github.com/llvm/llvm-project/pull/153845
Serves as an improvement to the current [`-fsanitize-debug-trap-reasons`](https://github.com/llvm/llvm-project/pull/145967) by providing additional context to the user regarding the trap reason. Part of a GSoC 2025 Project. >From 13140e96b9fa67e3258a036bf2a19ae78d7a0b40 Mon Sep 17 00:00:00 2001 From: Anthony Tran <atran...@usc.edu> Date: Fri, 15 Aug 2025 10:16:07 -0700 Subject: [PATCH] Add extra context for trap messages --- clang/lib/CodeGen/CGExpr.cpp | 105 +++++++++++++++--- clang/lib/CodeGen/CGExprScalar.cpp | 53 +++++++-- clang/lib/CodeGen/CodeGenFunction.h | 14 ++- .../CodeGen/ubsan-trap-reason-add-overflow.c | 22 +++- .../ubsan-trap-reason-div-rem-overflow.c | 18 ++- clang/test/CodeGen/ubsan-trap-reason-flag.c | 2 +- .../ubsan-trap-reason-float-cast-overflow.c | 2 +- ...ubsan-trap-reason-function-type-mismatch.c | 2 +- .../ubsan-trap-reason-implicit-conversion.c | 48 ++++++-- .../CodeGen/ubsan-trap-reason-mul-overflow.c | 22 +++- .../ubsan-trap-reason-negate-overflow.c | 2 +- .../ubsan-trap-reason-shift-out-of-bounds.c | 25 ++++- .../CodeGen/ubsan-trap-reason-sub-overflow.c | 22 +++- 13 files changed, 270 insertions(+), 67 deletions(-) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d5df6dd3e303c..9622db24c97e0 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -23,6 +23,7 @@ #include "CodeGenModule.h" #include "CodeGenPGO.h" #include "ConstantEmitter.h" +#include "SanitizerHandler.h" #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" @@ -37,6 +38,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" @@ -44,6 +46,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/xxhash.h" @@ -85,15 +88,84 @@ enum VariableTypeDescriptorKind : uint16_t { // Miscellaneous Helper Methods //===--------------------------------------------------------------------===// -static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { - switch (ID) { -#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ - case SanitizerHandler::Enum: \ - return Msg; - LIST_SANITIZER_CHECKS -#undef SANITIZER_CHECK +std::string CodeGenFunction::BuildSanitizerTrapMessage( + SanitizerHandler Handler, QualType LhsTy, QualType OpType, bool IsLeftShift, + bool IsSigned, std::string ReasonStr, bool IsDivideByZero, + bool IsTruncation) { + switch (Handler) { + case SanitizerHandler::AddOverflow: + return llvm::formatv("{0} integer addition overflow on type '{1}'", + IsSigned ? "Signed" : "Unsigned", LhsTy.getAsString()); + case SanitizerHandler::BuiltinUnreachable: + return "_builtin_unreachable(), execution reached an unreachable program " + "point"; + case SanitizerHandler::CFICheckFail: + return "Control flow integrity check failed"; + case SanitizerHandler::DivremOverflow: + return llvm::formatv("{0} on type '{1}'", ReasonStr, LhsTy.getAsString()); + case SanitizerHandler::DynamicTypeCacheMiss: + return "Dynamic type cache miss, member call made on an object whose " + "dynamic type differs from the expected type"; + case SanitizerHandler::FloatCastOverflow: + return llvm::formatv("Float cast overflow converting from floating-point " + "type '{0}' to integer type '{1}'", + LhsTy.getAsString(), OpType.getAsString()); + case SanitizerHandler::FunctionTypeMismatch: + return llvm::formatv("Call through function pointer of type '{0}' with an " + "incompatible target", + (LhsTy->getPointeeType()).getAsString()); + case SanitizerHandler::ImplicitConversion: + return llvm::formatv( + "Implicit {0}conversion from '{1}' to '{2}' caused {3}", + IsTruncation ? (IsSigned ? "signed " : "unsigned ") : "", + LhsTy.getAsString(), OpType.getAsString(), + IsTruncation ? "truncation" : "sign-change"); + case SanitizerHandler::InvalidBuiltin: + return "Invalid use of builtin function"; + case SanitizerHandler::InvalidObjCCast: + return "Invalid Objective-C cast"; + case SanitizerHandler::LoadInvalidValue: + return "Loaded an invalid or uninitialized value for the type"; + case SanitizerHandler::MissingReturn: + return "Execution reached the end of a value-returning function without " + "returning a value"; + case SanitizerHandler::MulOverflow: + return llvm::formatv("{0} integer multiplication overflow on type '{1}'", + IsSigned ? "Signed" : "Unsigned", LhsTy.getAsString()); + case SanitizerHandler::NegateOverflow: + return llvm::formatv("Integer negation overflow on type '{0}'", + LhsTy.getAsString()); + case SanitizerHandler::NullabilityArg: + return "Passing null as an argument which is annotated with _Nonnull"; + case SanitizerHandler::NullabilityReturn: + return "Returning null from a function with a return type annotated with " + "_Nonnull"; + case SanitizerHandler::NonnullArg: + return "Passing null pointer as an argument which is declared to never be " + "null"; + case SanitizerHandler::NonnullReturn: + return "Returning null pointer from a function which is declared to never " + "return null"; + case SanitizerHandler::OutOfBounds: + return "Array index out of bounds"; + case SanitizerHandler::PointerOverflow: + return "Pointer arithmetic overflowed bounds"; + case SanitizerHandler::ShiftOutOfBounds: + return llvm::formatv("{0} shift is too large for {1}-bit type '{2}'", + IsLeftShift ? "Left" : "Right", + getContext().getIntWidth(LhsTy), LhsTy.getAsString()); + case SanitizerHandler::SubOverflow: + return llvm::formatv("{0} integer subtraction overflow on type '{1}'", + IsSigned ? "Signed" : "Unsigned", LhsTy.getAsString()); + case SanitizerHandler::TypeMismatch: + return "Type mismatch in operation"; + case SanitizerHandler::AlignmentAssumption: + return "Alignment assumption violated"; + case SanitizerHandler::VLABoundNotPositive: + return "Variable length array bound evaluates to non-positive value"; + default: + return ""; } - llvm_unreachable("unhandled switch case"); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry @@ -3720,7 +3792,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, void CodeGenFunction::EmitCheck( ArrayRef<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>> Checked, SanitizerHandler CheckHandler, ArrayRef<llvm::Constant *> StaticArgs, - ArrayRef<llvm::Value *> DynamicArgs) { + ArrayRef<llvm::Value *> DynamicArgs, std::string TrapMessage) { assert(IsSanitizerScope); assert(Checked.size() > 0); assert(CheckHandler >= 0 && @@ -3759,7 +3831,7 @@ void CodeGenFunction::EmitCheck( } if (TrapCond) - EmitTrapCheck(TrapCond, CheckHandler, NoMerge); + EmitTrapCheck(TrapCond, CheckHandler, NoMerge, TrapMessage); if (!FatalCond && !RecoverableCond) return; @@ -4071,7 +4143,7 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) { void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, - bool NoMerge) { + bool NoMerge, std::string TrapMessage) { llvm::BasicBlock *Cont = createBasicBlock("cont"); // If we're optimizing, collapse all calls to trap down to just one per @@ -4082,7 +4154,11 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); - llvm::StringRef TrapMessage = GetUBSanTrapForHandler(CheckHandlerID); + // If no additional context was needed for building the trap message, we build + // it here instead + if (TrapMessage.empty()) { + TrapMessage = BuildSanitizerTrapMessage(CheckHandlerID, {}, {}); + } if (getDebugInfo() && !TrapMessage.empty() && CGM.getCodeGenOpts().SanitizeDebugTrapReasons && TrapLocation) { @@ -6404,8 +6480,11 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, Builder.CreateICmpEQ(CalleeTypeHash, TypeHash); llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getBeginLoc()), EmitCheckTypeDescriptor(CalleeType)}; + std::string Msg = + BuildSanitizerTrapMessage(SanitizerHandler::FunctionTypeMismatch, + CalleeType, {}, {}, {}, {}, {}); EmitCheck(std::make_pair(CalleeTypeHashMatch, CheckOrdinal), CheckHandler, - StaticData, {CalleePtr}); + StaticData, {CalleePtr}, Msg); Builder.CreateBr(Cont); EmitBlock(Cont); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 155b80df36715..66f082a030a21 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -31,6 +31,7 @@ #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/APFixedPoint.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/Argument.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" @@ -284,7 +285,7 @@ class ScalarExprEmitter void EmitBinOpCheck( ArrayRef<std::pair<Value *, SanitizerKind::SanitizerOrdinal>> Checks, - const BinOpInfo &Info); + const BinOpInfo &Info, std::string TrapMessage = ""); Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) { return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal(); @@ -1058,8 +1059,12 @@ void ScalarExprEmitter::EmitFloatConversionCheck( llvm::Constant *StaticArgs[] = {CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(OrigSrcType), CGF.EmitCheckTypeDescriptor(DstType)}; + std::string Msg = + CGF.BuildSanitizerTrapMessage(SanitizerHandler::FloatCastOverflow, + OrigSrcType, DstType, {}, {}, {}, {}); + CGF.EmitCheck(std::make_pair(Check, CheckOrdinal), CheckHandler, StaticArgs, - OrigSrc); + OrigSrc, Msg); } // Should be called within CodeGenFunction::SanitizerScope RAII scope. @@ -1172,7 +1177,11 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType, llvm::ConstantInt::get(Builder.getInt8Ty(), Check.first), llvm::ConstantInt::get(Builder.getInt32Ty(), 0)}; - CGF.EmitCheck(Check.second, CheckHandler, StaticArgs, {Src, Dst}); + std::string Msg = CGF.BuildSanitizerTrapMessage( + SanitizerHandler::ImplicitConversion, SrcType, DstType, {}, + (SrcSigned || DstSigned), {}, {}, true); + + CGF.EmitCheck(Check.second, CheckHandler, StaticArgs, {Src, Dst}, Msg); } static llvm::Value *EmitIsNegativeTestHelper(Value *V, QualType VType, @@ -1327,8 +1336,11 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, CGF.EmitCheckTypeDescriptor(DstType), llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind), llvm::ConstantInt::get(Builder.getInt32Ty(), 0)}; + std::string Msg = CGF.BuildSanitizerTrapMessage( + SanitizerHandler::ImplicitConversion, SrcType, DstType, {}, + (SrcSigned || DstSigned), {}, {}, false); // EmitCheck() will 'and' all the checks together. - CGF.EmitCheck(Checks, CheckHandler, StaticArgs, {Src, Dst}); + CGF.EmitCheck(Checks, CheckHandler, StaticArgs, {Src, Dst}, Msg); } // Should be called within CodeGenFunction::SanitizerScope RAII scope. @@ -1808,7 +1820,7 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) { /// are \c true. void ScalarExprEmitter::EmitBinOpCheck( ArrayRef<std::pair<Value *, SanitizerKind::SanitizerOrdinal>> Checks, - const BinOpInfo &Info) { + const BinOpInfo &Info, std::string TrapMessage) { assert(CGF.IsSanitizerScope); SanitizerHandler Check; SmallVector<llvm::Constant *, 4> StaticData; @@ -1824,6 +1836,8 @@ void ScalarExprEmitter::EmitBinOpCheck( Check = SanitizerHandler::NegateOverflow; StaticData.push_back(CGF.EmitCheckTypeDescriptor(UO->getType())); DynamicData.push_back(Info.RHS); + TrapMessage = CGF.BuildSanitizerTrapMessage(Check, UO->getType(), {}, false, + true, {}, {}, {}); } else { if (BinaryOperator::isShiftOp(Opcode)) { // Shift LHS negative or too large, or RHS out of bounds. @@ -1851,7 +1865,7 @@ void ScalarExprEmitter::EmitBinOpCheck( DynamicData.push_back(Info.RHS); } - CGF.EmitCheck(Checks, Check, StaticData, DynamicData); + CGF.EmitCheck(Checks, Check, StaticData, DynamicData, TrapMessage); } //===----------------------------------------------------------------------===// @@ -3969,8 +3983,10 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) { SmallVector<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>, 2> Checks; + std::string ReasonStr; if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) { + ReasonStr = "Division by zero"; Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero), SanitizerKind::SO_IntegerDivideByZero)); } @@ -3991,10 +4007,18 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or"); Checks.push_back( std::make_pair(NotOverflow, SanitizerKind::SO_SignedIntegerOverflow)); + if (!ReasonStr.empty()) { + ReasonStr += " or signed integer division overflow"; + } else { + ReasonStr = "Signed integer division overflow"; + } } - if (Checks.size() > 0) - EmitBinOpCheck(Checks, Ops); + if (Checks.size() > 0) { + std::string Msg = CGF.BuildSanitizerTrapMessage( + SanitizerHandler::DivremOverflow, Ops.Ty, {}, {}, {}, ReasonStr, {}); + EmitBinOpCheck(Checks, Ops, Msg); + } } Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { @@ -4132,7 +4156,9 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { SanitizerKind::SanitizerOrdinal Ordinal = isSigned ? SanitizerKind::SO_SignedIntegerOverflow : SanitizerKind::SO_UnsignedIntegerOverflow; - EmitBinOpCheck(std::make_pair(NotOverflow, Ordinal), Ops); + std::string Msg = CGF.BuildSanitizerTrapMessage(OverflowKind, Ops.Ty, {}, + {}, isSigned, {}, {}); + EmitBinOpCheck(std::make_pair(NotOverflow, Ordinal), Ops, Msg); } else CGF.EmitTrapCheck(Builder.CreateNot(overflow), OverflowKind); return result; @@ -4774,6 +4800,8 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { RHS = ConstrainShiftValue(Ops.LHS, RHS, "shl.mask"); else if ((SanitizeBase || SanitizeExponent) && isa<llvm::IntegerType>(Ops.LHS->getType())) { + std::string Msg = CGF.BuildSanitizerTrapMessage( + SanitizerHandler::ShiftOutOfBounds, Ops.Ty, {}, true, {}, {}, {}); SmallVector<SanitizerKind::SanitizerOrdinal, 3> Ordinals; if (SanitizeSignedBase) Ordinals.push_back(SanitizerKind::SO_ShiftBase); @@ -4832,7 +4860,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { } assert(!Checks.empty()); - EmitBinOpCheck(Checks, Ops); + EmitBinOpCheck(Checks, Ops, Msg); } return Builder.CreateShl(Ops.LHS, RHS, "shl"); @@ -4859,7 +4887,10 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation(); llvm::Value *Valid = Builder.CreateICmpULE( Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned)); - EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::SO_ShiftExponent), Ops); + std::string Msg = CGF.BuildSanitizerTrapMessage( + SanitizerHandler::ShiftOutOfBounds, Ops.Ty, {}, false, {}, {}, {}); + EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::SO_ShiftExponent), Ops, + Msg); } if (Ops.Ty->hasUnsignedIntegerRepresentation()) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index ad318f289ee83..c6d2df8025aa2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -38,12 +38,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/SanitizerStats.h" #include <optional> +#include <string> namespace llvm { class BasicBlock; @@ -636,6 +638,14 @@ class CodeGenFunction : public CodeGenTypeCache { /// condition is a known constant. bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody); + std::string BuildSanitizerTrapMessage(SanitizerHandler Handler, + QualType LhsTy, QualType OpType, + bool IsLeftShift = false, + bool isSigned = false, + std::string ReasonStr = "", + bool IsDivideByZero = false, + bool IsTruncation = false); + const CodeGen::CGBlockInfo *BlockInfo = nullptr; llvm::Value *BlockPointer = nullptr; @@ -5273,7 +5283,7 @@ class CodeGenFunction : public CodeGenTypeCache { EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>> Checked, SanitizerHandler Check, ArrayRef<llvm::Constant *> StaticArgs, - ArrayRef<llvm::Value *> DynamicArgs); + ArrayRef<llvm::Value *> DynamicArgs, std::string TrapMessage = ""); /// Emit a slow path cross-DSO CFI check which calls __cfi_slowpath /// if Cond if false. @@ -5289,7 +5299,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, - bool NoMerge = false); + bool NoMerge = false, std::string TrapMesage = ""); /// Emit a call to trap or debugtrap and attach function attribute /// "trap-func-name" if specified. diff --git a/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c index 225778d68833d..eee47538ceb0c 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c +++ b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c @@ -1,9 +1,19 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ -// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=SIO -int add_overflow(int a, int b) { return a + b; } +int signed_add_overflow(int a, int b) { return a + b; } -// CHECK-LABEL: @add_overflow -// CHECK: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] -// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed" +// SIO-LABEL: @signed_add_overflow +// SIO: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// SIO: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// SIO: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Signed integer addition overflow on type 'int'" + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=unsigned-integer-overflow -fsanitize-trap=unsigned-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=UIO + +unsigned int unsigned_add_overflow(unsigned int a, unsigned int b) { return a + b; } + +// UIO-LABEL: @unsigned_add_overflow +// UIO: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// UIO: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// UIO: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Unsigned integer addition overflow on type 'unsigned int'" diff --git a/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c index d0b21dd173894..e6567a82d0b39 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c +++ b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c @@ -1,9 +1,17 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ -// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=SIO + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=integer-divide-by-zero -fsanitize-trap=integer-divide-by-zero -emit-llvm %s -o - | FileCheck %s --check-prefix=DBZ int div_rem_overflow(int a, int b) { return a / b; } -// CHECK-LABEL: @div_rem_overflow -// CHECK: call void @llvm.ubsantrap(i8 3) {{.*}}!dbg [[LOC:![0-9]+]] -// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer divide or remainder overflowed" +// SIO-LABEL: @div_rem_overflow +// SIO: call void @llvm.ubsantrap(i8 3) {{.*}}!dbg [[LOC:![0-9]+]] +// SIO: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// SIO: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Signed integer division overflow on type 'int'" + +// DBZ-LABEL: @div_rem_overflow +// DBZ: call void @llvm.ubsantrap(i8 3) {{.*}}!dbg [[LOC:![0-9]+]] +// DBZ: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// DBZ: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Division by zero on type 'int'" diff --git a/clang/test/CodeGen/ubsan-trap-reason-flag.c b/clang/test/CodeGen/ubsan-trap-reason-flag.c index 5cc16d154bf68..94f529c1566a9 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-flag.c +++ b/clang/test/CodeGen/ubsan-trap-reason-flag.c @@ -15,7 +15,7 @@ int add_overflow(int a, int b) { return a + b; } // ANNOTATE-LABEL: @add_overflow // ANNOTATE: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] // ANNOTATE: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// ANNOTATE: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed" +// ANNOTATE: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Signed integer addition overflow on type 'int'" // NO-ANNOTATE-LABEL: @add_overflow // NO-ANNOTATE: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] diff --git a/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c index 079a191e05d4b..d7d26fa692175 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c +++ b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c @@ -6,4 +6,4 @@ int float_cast_overflow(float x) { return (int)x; } // CHECK-LABEL: @float_cast_overflow // CHECK: call void @llvm.ubsantrap(i8 5) {{.*}}!dbg [[LOC:![0-9]+]] // CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Floating-point to integer conversion overflowed" +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Float cast overflow converting from floating-point type 'float' to integer type 'int'" diff --git a/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c index 1727f9c092a4c..6808dcf2a654f 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c +++ b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c @@ -15,4 +15,4 @@ int function_type_mismatch(void) { // CHECK-LABEL: @function_type_mismatch // CHECK: call void @llvm.ubsantrap(i8 6) {{.*}}!dbg [[LOC:![0-9]+]] // CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Function called with mismatched signature" +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Call through function pointer of type 'int (int)' with an incompatible target" diff --git a/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c index 43c091d51a5c2..ae4caabbc6abf 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c +++ b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c @@ -1,11 +1,43 @@ -// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ -// RUN: -fsanitize=implicit-unsigned-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 -fsanitize=implicit-signed-integer-truncation \ +// RUN: -fsanitize-trap=implicit-signed-integer-truncation -emit-llvm %s -o - | FileCheck %s --check-prefix=SIC -unsigned long long big; +long long signedBig; -unsigned implicit_conversion(void) { return big; } +int signed_implicit_conversion_truncation(void) { return signedBig; } -// CHECK-LABEL: @implicit_conversion -// CHECK: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC:![0-9]+]] -// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Implicit integer conversion overflowed or lost data" +// SIC-LABEL: @signed_implicit_conversion_truncation +// SIC: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC:![0-9]+]] +// SIC: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// SIC: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Implicit signed conversion from 'long long' to 'int' caused truncation" + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 -fsanitize=implicit-unsigned-integer-truncation \ +// RUN: -fsanitize-trap=implicit-unsigned-integer-truncation -emit-llvm %s -o - | FileCheck %s --check-prefix=UIC + +unsigned long long unsignedBig; + +unsigned unsigned_implicit_conversion_truncation(void) { return unsignedBig; } + +// UIC-LABEL: @unsigned_implicit_conversion_truncation +// UIC: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC:![0-9]+]] +// UIC: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// UIC: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Implicit unsigned conversion from 'unsigned long long' to 'unsigned int' caused truncation" + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 -fsanitize=implicit-integer-sign-change \ +// RUN: -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - | FileCheck %s --check-prefix=ISCUFS + +unsigned to_unsigned_from_signed(int x) { return x; } + +// ISCUFS-LABEL: @to_unsigned_from_signed +// ISCUFS: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC1:![0-9]+]] +// ISCUFS: [[LOC1]] = !DILocation(line: 0, scope: [[MSG1:![0-9]+]], {{.+}}) +// ISCUFS: [[MSG1]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Implicit conversion from 'int' to 'unsigned int' caused sign-change" + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 -fsanitize=implicit-integer-sign-change \ +// RUN: -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - | FileCheck %s --check-prefix=ISCSFU + +int to_signed_from_unsigned(unsigned x) { return x; } + +// ISCSFU-LABEL: @to_signed_from_unsigned +// ISCSFU: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC2:![0-9]+]] +// ISCSFU: [[LOC2]] = !DILocation(line: 0, scope: [[MSG2:![0-9]+]], {{.+}}) +// ISCSFU: [[MSG2]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Implicit conversion from 'unsigned int' to 'int' caused sign-change" diff --git a/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c index cf9a0b4e7439c..6b86527087f88 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c +++ b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c @@ -1,9 +1,19 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ -// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=SIO -int mul_overflow(int a, int b) { return a * b; } +int signed_mul_overflow(int a, int b) { return a * b; } -// CHECK-LABEL: @mul_overflow -// CHECK: call void @llvm.ubsantrap(i8 12) {{.*}}!dbg [[LOC:![0-9]+]] -// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer multiplication overflowed" +// SIO-LABEL: @signed_mul_overflow +// SIO: call void @llvm.ubsantrap(i8 12) {{.*}}!dbg [[LOC:![0-9]+]] +// SIO: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// SIO: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Signed integer multiplication overflow on type 'int'" + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=unsigned-integer-overflow -fsanitize-trap=unsigned-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=UIO + +unsigned unsigned_mul_overflow(unsigned a, unsigned b) { return a * b; } + +// UIO-LABEL: @unsigned_mul_overflow +// UIO: call void @llvm.ubsantrap(i8 12) {{.*}}!dbg [[LOC:![0-9]+]] +// UIO: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// UIO: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Unsigned integer multiplication overflow on type 'unsigned int'" diff --git a/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c index 55346794b2928..76302b95ca8df 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c +++ b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c @@ -9,4 +9,4 @@ int negate_overflow() { // CHECK-LABEL: @negate_overflow // CHECK: call void @llvm.ubsantrap(i8 13) {{.*}}!dbg [[LOC:![0-9]+]] // CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer negation overflowed" +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer negation overflow on type 'int'" diff --git a/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c index 1a7465d93aef5..eed4eb411c3da 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c +++ b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c @@ -1,12 +1,25 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ -// RUN: -fsanitize=shift-base -fsanitize-trap=shift-base -emit-llvm %s -o - | FileCheck %s +// RUN: -fsanitize=shift-exponent -fsanitize-trap=shift-exponent -emit-llvm %s -o - | FileCheck %s --check-prefix=RS -int shift_out_of_bounds(void) { +int right_shift_out_of_bounds(void) { + int sh = 32; + return 1 >> sh; +} + +// RS-LABEL: @right_shift_out_of_bounds +// RS: call void @llvm.ubsantrap(i8 20) {{.*}}!dbg [[LOC:![0-9]+]] +// RS: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// RS: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Right shift is too large for 32-bit type 'int'" + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=shift-exponent -fsanitize-trap=shift-exponent -emit-llvm %s -o - | FileCheck %s --check-prefix=LS + +int left_shift_out_of_bounds(void) { int sh = 32; return 1 << sh; } -// CHECK-LABEL: @shift_out_of_bounds -// CHECK: call void @llvm.ubsantrap(i8 20) {{.*}}!dbg [[LOC:![0-9]+]] -// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Shift exponent is too large for the type" +// LS-LABEL: @left_shift_out_of_bounds +// LS: call void @llvm.ubsantrap(i8 20) {{.*}}!dbg [[LOC:![0-9]+]] +// LS: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// LS: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Left shift is too large for 32-bit type 'int'" diff --git a/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c index 62aa7fc953dad..4eddc9d5fee08 100644 --- a/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c +++ b/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c @@ -1,9 +1,19 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ -// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=SIO -int sub_overflow(int a, int b) { return a - b; } +int signed_sub_overflow(int a, int b) { return a - b; } -// CHECK-LABEL: @sub_overflow -// CHECK: call void @llvm.ubsantrap(i8 21) {{.*}}!dbg [[LOC:![0-9]+]] -// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) -// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer subtraction overflowed" +// SIO-LABEL: @signed_sub_overflow +// SIO: call void @llvm.ubsantrap(i8 21) {{.*}}!dbg [[LOC:![0-9]+]] +// SIO: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// SIO: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Signed integer subtraction overflow on type 'int'" + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=unsigned-integer-overflow -fsanitize-trap=unsigned-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=UIO + +unsigned int unsigned_sub_overflow(unsigned int a, unsigned int b) { return a - b; } + +// UIO-LABEL: @unsigned_sub_overflow +// UIO: call void @llvm.ubsantrap(i8 21) {{.*}}!dbg [[LOC:![0-9]+]] +// UIO: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// UIO: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Unsigned integer subtraction overflow on type 'unsigned int'" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits