Skip to content

Commit 428afa6

Browse files
[ubsan] Add more -fsanitize-annotate-debug-info checks (#141997)
This extends #138577 to more UBSan checks, by changing SanitizerDebugLocation (formerly SanitizerScope) to add annotations if enabled for the specified ordinals. Annotations will use the ordinal name if there is exactly one ordinal specified in the SanitizerDebugLocation; otherwise, it will use the handler name. Updates the tests from #141814. --------- Co-authored-by: Vitaly Buka <[email protected]>
1 parent a42bb8b commit 428afa6

14 files changed

+411
-256
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,11 +2009,12 @@ Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E,
20092009
if (!SanOpts.has(SanitizerKind::Builtin))
20102010
return ArgValue;
20112011

2012-
SanitizerScope SanScope(this);
2012+
auto CheckOrdinal = SanitizerKind::SO_Builtin;
2013+
auto CheckHandler = SanitizerHandler::InvalidBuiltin;
2014+
SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
20132015
Value *Cond = Builder.CreateICmpNE(
20142016
ArgValue, llvm::Constant::getNullValue(ArgValue->getType()));
2015-
EmitCheck(std::make_pair(Cond, SanitizerKind::SO_Builtin),
2016-
SanitizerHandler::InvalidBuiltin,
2017+
EmitCheck(std::make_pair(Cond, CheckOrdinal), CheckHandler,
20172018
{EmitCheckSourceLocation(E->getExprLoc()),
20182019
llvm::ConstantInt::get(Builder.getInt8Ty(), Kind)},
20192020
{});
@@ -2025,10 +2026,11 @@ Value *CodeGenFunction::EmitCheckedArgForAssume(const Expr *E) {
20252026
if (!SanOpts.has(SanitizerKind::Builtin))
20262027
return ArgValue;
20272028

2028-
SanitizerScope SanScope(this);
2029+
auto CheckOrdinal = SanitizerKind::SO_Builtin;
2030+
auto CheckHandler = SanitizerHandler::InvalidBuiltin;
2031+
SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
20292032
EmitCheck(
2030-
std::make_pair(ArgValue, SanitizerKind::SO_Builtin),
2031-
SanitizerHandler::InvalidBuiltin,
2033+
std::make_pair(ArgValue, CheckOrdinal), CheckHandler,
20322034
{EmitCheckSourceLocation(E->getExprLoc()),
20332035
llvm::ConstantInt::get(Builder.getInt8Ty(), BCK_AssumePassedFalse)},
20342036
std::nullopt);
@@ -2051,7 +2053,15 @@ static Value *EmitOverflowCheckedAbs(CodeGenFunction &CGF, const CallExpr *E,
20512053
return EmitAbs(CGF, ArgValue, true);
20522054
}
20532055

2054-
CodeGenFunction::SanitizerScope SanScope(&CGF);
2056+
SmallVector<SanitizerKind::SanitizerOrdinal, 1> Ordinals;
2057+
SanitizerHandler CheckHandler;
2058+
if (SanitizeOverflow) {
2059+
Ordinals.push_back(SanitizerKind::SO_SignedIntegerOverflow);
2060+
CheckHandler = SanitizerHandler::NegateOverflow;
2061+
} else
2062+
CheckHandler = SanitizerHandler::SubOverflow;
2063+
2064+
SanitizerDebugLocation SanScope(&CGF, Ordinals, CheckHandler);
20552065

20562066
Constant *Zero = Constant::getNullValue(ArgValue->getType());
20572067
Value *ResultAndOverflow = CGF.Builder.CreateBinaryIntrinsic(
@@ -2063,12 +2073,12 @@ static Value *EmitOverflowCheckedAbs(CodeGenFunction &CGF, const CallExpr *E,
20632073
// TODO: support -ftrapv-handler.
20642074
if (SanitizeOverflow) {
20652075
CGF.EmitCheck({{NotOverflow, SanitizerKind::SO_SignedIntegerOverflow}},
2066-
SanitizerHandler::NegateOverflow,
2076+
CheckHandler,
20672077
{CGF.EmitCheckSourceLocation(E->getArg(0)->getExprLoc()),
20682078
CGF.EmitCheckTypeDescriptor(E->getType())},
20692079
{ArgValue});
20702080
} else
2071-
CGF.EmitTrapCheck(NotOverflow, SanitizerHandler::SubOverflow);
2081+
CGF.EmitTrapCheck(NotOverflow, CheckHandler);
20722082

20732083
Value *CmpResult = CGF.Builder.CreateICmpSLT(ArgValue, Zero, "abscond");
20742084
return CGF.Builder.CreateSelect(CmpResult, Result, ArgValue, "abs");

clang/lib/CodeGen/CGCall.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4184,7 +4184,7 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
41844184
Handler = SanitizerHandler::NullabilityReturn;
41854185
}
41864186

4187-
SanitizerScope SanScope(this);
4187+
SanitizerDebugLocation SanScope(this, {CheckKind}, Handler);
41884188

41894189
// Make sure the "return" source location is valid. If we're checking a
41904190
// nullability annotation, make sure the preconditions for the check are met.
@@ -4569,7 +4569,7 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
45694569
Handler = SanitizerHandler::NullabilityArg;
45704570
}
45714571

4572-
SanitizerScope SanScope(this);
4572+
SanitizerDebugLocation SanScope(this, {CheckKind}, Handler);
45734573
llvm::Value *Cond = EmitNonNullRValueCheck(RV, ArgType);
45744574
llvm::Constant *StaticData[] = {
45754575
EmitCheckSourceLocation(ArgLoc),

clang/lib/CodeGen/CGClass.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2817,7 +2817,8 @@ void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
28172817
RD = LeastDerivedClassWithSameLayout(RD);
28182818

28192819
auto [Ordinal, _] = SanitizerInfoFromCFICheckKind(TCK);
2820-
ApplyDebugLocation ApplyTrapDI(*this, SanitizerAnnotateDebugInfo(Ordinal));
2820+
SanitizerDebugLocation SanScope(this, {Ordinal},
2821+
SanitizerHandler::CFICheckFail);
28212822

28222823
EmitVTablePtrCheck(RD, VTable, TCK, Loc);
28232824
}
@@ -2842,7 +2843,8 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived,
28422843
ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
28432844

28442845
auto [Ordinal, _] = SanitizerInfoFromCFICheckKind(TCK);
2845-
ApplyDebugLocation ApplyTrapDI(*this, SanitizerAnnotateDebugInfo(Ordinal));
2846+
SanitizerDebugLocation SanScope(this, {Ordinal},
2847+
SanitizerHandler::CFICheckFail);
28462848

28472849
llvm::BasicBlock *ContBlock = nullptr;
28482850

@@ -2874,6 +2876,8 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
28742876
llvm::Value *VTable,
28752877
CFITypeCheckKind TCK,
28762878
SourceLocation Loc) {
2879+
assert(IsSanitizerScope);
2880+
28772881
if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
28782882
!CGM.HasHiddenLTOVisibility(RD))
28792883
return;
@@ -2885,7 +2889,6 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
28852889
SanitizerMask::bitPosToMask(M), TypeName))
28862890
return;
28872891

2888-
SanitizerScope SanScope(this);
28892892
EmitSanitizerStatReport(SSK);
28902893

28912894
llvm::Metadata *MD =
@@ -2942,11 +2945,11 @@ bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
29422945
llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
29432946
const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,
29442947
uint64_t VTableByteOffset) {
2945-
SanitizerScope SanScope(this);
2948+
auto CheckOrdinal = SanitizerKind::SO_CFIVCall;
2949+
auto CheckHandler = SanitizerHandler::CFICheckFail;
2950+
SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
29462951

29472952
EmitSanitizerStatReport(llvm::SanStat_CFI_VCall);
2948-
ApplyDebugLocation ApplyTrapDI(
2949-
*this, SanitizerAnnotateDebugInfo(SanitizerKind::SO_CFIVCall));
29502953

29512954
llvm::Metadata *MD =
29522955
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
@@ -2965,8 +2968,7 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
29652968
if (SanOpts.has(SanitizerKind::CFIVCall) &&
29662969
!getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
29672970
TypeName)) {
2968-
EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIVCall),
2969-
SanitizerHandler::CFICheckFail, {}, {});
2971+
EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});
29702972
}
29712973

29722974
return Builder.CreateBitCast(Builder.CreateExtractValue(CheckedLoad, 0),

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@
5858
using namespace clang;
5959
using namespace clang::CodeGen;
6060

61+
// TODO: consider deprecating ClArrayBoundsPseudoFn; functionality is subsumed
62+
// by -fsanitize-annotate-debug-info
63+
static llvm::cl::opt<bool> ClArrayBoundsPseudoFn(
64+
"array-bounds-pseudofn", llvm::cl::Hidden, llvm::cl::Optional,
65+
llvm::cl::desc("Emit debug info that places array-bounds instrumentation "
66+
"in an inline function called __ubsan_check_array_bounds."));
67+
6168
static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
6269
auto TI = Ctx.getTypeInfo(Ty);
6370
if (TI.isAlignRequired())
@@ -6412,3 +6419,78 @@ CodeGenFunction::LexicalScope::~LexicalScope() {
64126419
ForceCleanup();
64136420
}
64146421
}
6422+
6423+
static std::string SanitizerHandlerToCheckLabel(SanitizerHandler Handler) {
6424+
std::string Label;
6425+
switch (Handler) {
6426+
#define SANITIZER_CHECK(Enum, Name, Version) \
6427+
case Enum: \
6428+
Label = "__ubsan_check_" #Name; \
6429+
break;
6430+
6431+
LIST_SANITIZER_CHECKS
6432+
#undef SANITIZER_CHECK
6433+
};
6434+
6435+
// Label doesn't require sanitization
6436+
return Label;
6437+
}
6438+
6439+
static std::string
6440+
SanitizerOrdinalToCheckLabel(SanitizerKind::SanitizerOrdinal Ordinal) {
6441+
std::string Label;
6442+
switch (Ordinal) {
6443+
#define SANITIZER(NAME, ID) \
6444+
case SanitizerKind::SO_##ID: \
6445+
Label = "__ubsan_check_" NAME; \
6446+
break;
6447+
#include "clang/Basic/Sanitizers.def"
6448+
default:
6449+
llvm_unreachable("unexpected sanitizer kind");
6450+
}
6451+
6452+
// Sanitize label (convert hyphens to underscores; also futureproof against
6453+
// non-alpha)
6454+
for (unsigned int i = 0; i < Label.length(); i++)
6455+
if (!std::isalpha(Label[i]))
6456+
Label[i] = '_';
6457+
6458+
return Label;
6459+
}
6460+
6461+
llvm::DILocation *CodeGenFunction::SanitizerAnnotateDebugInfo(
6462+
ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
6463+
SanitizerHandler Handler) {
6464+
std::string Label;
6465+
if (Ordinals.size() == 1)
6466+
Label = SanitizerOrdinalToCheckLabel(Ordinals[0]);
6467+
else
6468+
Label = SanitizerHandlerToCheckLabel(Handler);
6469+
6470+
llvm::DILocation *CheckDI = Builder.getCurrentDebugLocation();
6471+
6472+
for (auto Ord : Ordinals) {
6473+
// TODO: deprecate ClArrayBoundsPseudoFn
6474+
if (((ClArrayBoundsPseudoFn && Ord == SanitizerKind::SO_ArrayBounds) ||
6475+
CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo.has(Ord)) &&
6476+
CheckDI) {
6477+
return getDebugInfo()->CreateSyntheticInlineAt(CheckDI, Label);
6478+
}
6479+
}
6480+
6481+
return CheckDI;
6482+
}
6483+
6484+
SanitizerDebugLocation::SanitizerDebugLocation(
6485+
CodeGenFunction *CGF, ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
6486+
SanitizerHandler Handler)
6487+
: CGF(CGF),
6488+
Apply(*CGF, CGF->SanitizerAnnotateDebugInfo(Ordinals, Handler)) {
6489+
assert(!CGF->IsSanitizerScope);
6490+
CGF->IsSanitizerScope = true;
6491+
}
6492+
6493+
SanitizerDebugLocation::~SanitizerDebugLocation() {
6494+
assert(CGF->IsSanitizerScope);
6495+
CGF->IsSanitizerScope = false;
6496+
}

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H
1515

1616
#include "CGBuilder.h"
17+
#include "SanitizerHandler.h"
1718
#include "clang/AST/DeclCXX.h"
1819
#include "clang/AST/Expr.h"
1920
#include "clang/AST/ExternalASTSource.h"
@@ -974,6 +975,17 @@ class ApplyInlineDebugLocation {
974975
~ApplyInlineDebugLocation();
975976
};
976977

978+
class SanitizerDebugLocation {
979+
CodeGenFunction *CGF;
980+
ApplyDebugLocation Apply;
981+
982+
public:
983+
SanitizerDebugLocation(CodeGenFunction *CGF,
984+
ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
985+
SanitizerHandler Handler);
986+
~SanitizerDebugLocation();
987+
};
988+
977989
} // namespace CodeGen
978990
} // namespace clang
979991

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -766,14 +766,15 @@ void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS,
766766

767767
// Check if the right hand side of the assignment is nonnull, if the left
768768
// hand side must be nonnull.
769-
SanitizerScope SanScope(this);
769+
auto CheckOrdinal = SanitizerKind::SO_NullabilityAssign;
770+
auto CheckHandler = SanitizerHandler::TypeMismatch;
771+
SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
770772
llvm::Value *IsNotNull = Builder.CreateIsNotNull(RHS);
771773
llvm::Constant *StaticData[] = {
772774
EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(LHS.getType()),
773775
llvm::ConstantInt::get(Int8Ty, 0), // The LogAlignment info is unused.
774776
llvm::ConstantInt::get(Int8Ty, TCK_NonnullAssign)};
775-
EmitCheck({{IsNotNull, SanitizerKind::SO_NullabilityAssign}},
776-
SanitizerHandler::TypeMismatch, StaticData, RHS);
777+
EmitCheck({{IsNotNull, CheckOrdinal}}, CheckHandler, StaticData, RHS);
777778
}
778779

779780
void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,

0 commit comments

Comments
 (0)