Skip to content

Commit 55b5875

Browse files
authored
[ubsan][NFCI] Use SanitizerOrdinal instead of SanitizerMask for EmitCheck (exactly one sanitizer is required) (#122511)
The `Checked` parameter of `CodeGenFunction::EmitCheck` is of type `ArrayRef<std::pair<llvm::Value *, SanitizerMask>>`, which is overly generalized: SanitizerMask can denote that zero or more sanitizers are enabled, but `EmitCheck` requires that exactly one sanitizer is specified in the SanitizerMask (e.g., `SanitizeTrap.has(Checked[i].second)` enforces that). This patch replaces SanitizerMask with SanitizerOrdinal in the `Checked` parameter of `EmitCheck` and code that transitively relies on it. This should not affect the behavior of UBSan, but it has the advantages that: - the code is clearer: it avoids ambiguity in EmitCheck about what to do if multiple bits are set - specifying the wrong number of sanitizers in `Checked[i].second` will be detected as a compile-time error, rather than a runtime assertion failure Suggested by Vitaly in #122392 as an alternative to adding an explicit runtime assertion that the SanitizerMask contains exactly one sanitizer.
1 parent 8e6261f commit 55b5875

File tree

11 files changed

+124
-100
lines changed

11 files changed

+124
-100
lines changed

clang/include/clang/Basic/Sanitizers.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ struct SanitizerSet {
171171
return static_cast<bool>(Mask & K);
172172
}
173173

174+
bool has(SanitizerKind::SanitizerOrdinal O) const {
175+
return has(SanitizerMask::bitPosToMask(O));
176+
}
177+
174178
/// Check if one or more sanitizers are enabled.
175179
bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
176180

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,7 +2240,7 @@ Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E,
22402240
SanitizerScope SanScope(this);
22412241
Value *Cond = Builder.CreateICmpNE(
22422242
ArgValue, llvm::Constant::getNullValue(ArgValue->getType()));
2243-
EmitCheck(std::make_pair(Cond, SanitizerKind::Builtin),
2243+
EmitCheck(std::make_pair(Cond, SanitizerKind::SO_Builtin),
22442244
SanitizerHandler::InvalidBuiltin,
22452245
{EmitCheckSourceLocation(E->getExprLoc()),
22462246
llvm::ConstantInt::get(Builder.getInt8Ty(), Kind)},
@@ -2255,7 +2255,7 @@ Value *CodeGenFunction::EmitCheckedArgForAssume(const Expr *E) {
22552255

22562256
SanitizerScope SanScope(this);
22572257
EmitCheck(
2258-
std::make_pair(ArgValue, SanitizerKind::Builtin),
2258+
std::make_pair(ArgValue, SanitizerKind::SO_Builtin),
22592259
SanitizerHandler::InvalidBuiltin,
22602260
{EmitCheckSourceLocation(E->getExprLoc()),
22612261
llvm::ConstantInt::get(Builder.getInt8Ty(), BCK_AssumePassedFalse)},
@@ -2290,7 +2290,7 @@ static Value *EmitOverflowCheckedAbs(CodeGenFunction &CGF, const CallExpr *E,
22902290

22912291
// TODO: support -ftrapv-handler.
22922292
if (SanitizeOverflow) {
2293-
CGF.EmitCheck({{NotOverflow, SanitizerKind::SignedIntegerOverflow}},
2293+
CGF.EmitCheck({{NotOverflow, SanitizerKind::SO_SignedIntegerOverflow}},
22942294
SanitizerHandler::NegateOverflow,
22952295
{CGF.EmitCheckSourceLocation(E->getArg(0)->getExprLoc()),
22962296
CGF.EmitCheckTypeDescriptor(E->getType())},

clang/lib/CodeGen/CGCall.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4024,20 +4024,20 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
40244024

40254025
// Prefer the returns_nonnull attribute if it's present.
40264026
SourceLocation AttrLoc;
4027-
SanitizerMask CheckKind;
4027+
SanitizerKind::SanitizerOrdinal CheckKind;
40284028
SanitizerHandler Handler;
40294029
if (RetNNAttr) {
40304030
assert(!requiresReturnValueNullabilityCheck() &&
40314031
"Cannot check nullability and the nonnull attribute");
40324032
AttrLoc = RetNNAttr->getLocation();
4033-
CheckKind = SanitizerKind::ReturnsNonnullAttribute;
4033+
CheckKind = SanitizerKind::SO_ReturnsNonnullAttribute;
40344034
Handler = SanitizerHandler::NonnullReturn;
40354035
} else {
40364036
if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl))
40374037
if (auto *TSI = DD->getTypeSourceInfo())
40384038
if (auto FTL = TSI->getTypeLoc().getAsAdjusted<FunctionTypeLoc>())
40394039
AttrLoc = FTL.getReturnLoc().findNullabilityLoc();
4040-
CheckKind = SanitizerKind::NullabilityReturn;
4040+
CheckKind = SanitizerKind::SO_NullabilityReturn;
40414041
Handler = SanitizerHandler::NullabilityReturn;
40424042
}
40434043

@@ -4419,15 +4419,15 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
44194419
return;
44204420

44214421
SourceLocation AttrLoc;
4422-
SanitizerMask CheckKind;
4422+
SanitizerKind::SanitizerOrdinal CheckKind;
44234423
SanitizerHandler Handler;
44244424
if (NNAttr) {
44254425
AttrLoc = NNAttr->getLocation();
4426-
CheckKind = SanitizerKind::NonnullAttribute;
4426+
CheckKind = SanitizerKind::SO_NonnullAttribute;
44274427
Handler = SanitizerHandler::NonnullArg;
44284428
} else {
44294429
AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc();
4430-
CheckKind = SanitizerKind::NullabilityArg;
4430+
CheckKind = SanitizerKind::SO_NullabilityArg;
44314431
Handler = SanitizerHandler::NullabilityArg;
44324432
}
44334433

clang/lib/CodeGen/CGClass.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,23 +2843,23 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
28432843
!CGM.HasHiddenLTOVisibility(RD))
28442844
return;
28452845

2846-
SanitizerMask M;
2846+
SanitizerKind::SanitizerOrdinal M;
28472847
llvm::SanitizerStatKind SSK;
28482848
switch (TCK) {
28492849
case CFITCK_VCall:
2850-
M = SanitizerKind::CFIVCall;
2850+
M = SanitizerKind::SO_CFIVCall;
28512851
SSK = llvm::SanStat_CFI_VCall;
28522852
break;
28532853
case CFITCK_NVCall:
2854-
M = SanitizerKind::CFINVCall;
2854+
M = SanitizerKind::SO_CFINVCall;
28552855
SSK = llvm::SanStat_CFI_NVCall;
28562856
break;
28572857
case CFITCK_DerivedCast:
2858-
M = SanitizerKind::CFIDerivedCast;
2858+
M = SanitizerKind::SO_CFIDerivedCast;
28592859
SSK = llvm::SanStat_CFI_DerivedCast;
28602860
break;
28612861
case CFITCK_UnrelatedCast:
2862-
M = SanitizerKind::CFIUnrelatedCast;
2862+
M = SanitizerKind::SO_CFIUnrelatedCast;
28632863
SSK = llvm::SanStat_CFI_UnrelatedCast;
28642864
break;
28652865
case CFITCK_ICall:
@@ -2869,7 +2869,8 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
28692869
}
28702870

28712871
std::string TypeName = RD->getQualifiedNameAsString();
2872-
if (getContext().getNoSanitizeList().containsType(M, TypeName))
2872+
if (getContext().getNoSanitizeList().containsType(
2873+
SanitizerMask::bitPosToMask(M), TypeName))
28732874
return;
28742875

28752876
SanitizerScope SanScope(this);
@@ -2945,7 +2946,7 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
29452946
if (SanOpts.has(SanitizerKind::CFIVCall) &&
29462947
!getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
29472948
TypeName)) {
2948-
EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall),
2949+
EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIVCall),
29492950
SanitizerHandler::CFICheckFail, {}, {});
29502951
}
29512952

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS,
762762
EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(LHS.getType()),
763763
llvm::ConstantInt::get(Int8Ty, 0), // The LogAlignment info is unused.
764764
llvm::ConstantInt::get(Int8Ty, TCK_NonnullAssign)};
765-
EmitCheck({{IsNotNull, SanitizerKind::NullabilityAssign}},
765+
EmitCheck({{IsNotNull, SanitizerKind::SO_NullabilityAssign}},
766766
SanitizerHandler::TypeMismatch, StaticData, RHS);
767767
}
768768

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
735735

736736
SanitizerScope SanScope(this);
737737

738-
SmallVector<std::pair<llvm::Value *, SanitizerMask>, 3> Checks;
738+
SmallVector<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>, 3>
739+
Checks;
739740
llvm::BasicBlock *Done = nullptr;
740741

741742
// Quickly determine whether we have a pointer to an alloca. It's possible
@@ -767,7 +768,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
767768
Builder.CreateCondBr(IsNonNull, Rest, Done);
768769
EmitBlock(Rest);
769770
} else {
770-
Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::Null));
771+
Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::SO_Null));
771772
}
772773
}
773774
}
@@ -794,7 +795,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
794795
llvm::Value *Dynamic = Builder.getFalse();
795796
llvm::Value *LargeEnough = Builder.CreateICmpUGE(
796797
Builder.CreateCall(F, {Ptr, Min, NullIsUnknown, Dynamic}), Size);
797-
Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));
798+
Checks.push_back(
799+
std::make_pair(LargeEnough, SanitizerKind::SO_ObjectSize));
798800
}
799801
}
800802

@@ -818,7 +820,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
818820
llvm::Value *Aligned =
819821
Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
820822
if (Aligned != True)
821-
Checks.push_back(std::make_pair(Aligned, SanitizerKind::Alignment));
823+
Checks.push_back(std::make_pair(Aligned, SanitizerKind::SO_Alignment));
822824
}
823825
}
824826

@@ -902,7 +904,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
902904
llvm::ConstantInt::get(Int8Ty, TCK)
903905
};
904906
llvm::Value *DynamicData[] = { Ptr, Hash };
905-
EmitCheck(std::make_pair(EqualHash, SanitizerKind::Vptr),
907+
EmitCheck(std::make_pair(EqualHash, SanitizerKind::SO_Vptr),
906908
SanitizerHandler::DynamicTypeCacheMiss, StaticData,
907909
DynamicData);
908910
}
@@ -1220,7 +1222,7 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
12201222
};
12211223
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
12221224
: Builder.CreateICmpULE(IndexVal, BoundVal);
1223-
EmitCheck(std::make_pair(Check, SanitizerKind::ArrayBounds),
1225+
EmitCheck(std::make_pair(Check, SanitizerKind::SO_ArrayBounds),
12241226
SanitizerHandler::OutOfBounds, StaticData, Index);
12251227
}
12261228

@@ -1960,8 +1962,8 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
19601962
}
19611963
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc),
19621964
EmitCheckTypeDescriptor(Ty)};
1963-
SanitizerMask Kind =
1964-
NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool;
1965+
SanitizerKind::SanitizerOrdinal Kind =
1966+
NeedsEnumCheck ? SanitizerKind::SO_Enum : SanitizerKind::SO_Bool;
19651967
EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue,
19661968
StaticArgs, EmitCheckValue(Value));
19671969
return true;
@@ -3513,11 +3515,12 @@ enum class CheckRecoverableKind {
35133515
};
35143516
}
35153517

3516-
static CheckRecoverableKind getRecoverableKind(SanitizerMask Kind) {
3517-
assert(Kind.countPopulation() == 1);
3518-
if (Kind == SanitizerKind::Vptr)
3518+
static CheckRecoverableKind
3519+
getRecoverableKind(SanitizerKind::SanitizerOrdinal Ordinal) {
3520+
if (Ordinal == SanitizerKind::SO_Vptr)
35193521
return CheckRecoverableKind::AlwaysRecoverable;
3520-
else if (Kind == SanitizerKind::Return || Kind == SanitizerKind::Unreachable)
3522+
else if (Ordinal == SanitizerKind::SO_Return ||
3523+
Ordinal == SanitizerKind::SO_Unreachable)
35213524
return CheckRecoverableKind::Unrecoverable;
35223525
else
35233526
return CheckRecoverableKind::Recoverable;
@@ -3589,7 +3592,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
35893592
}
35903593

35913594
void CodeGenFunction::EmitCheck(
3592-
ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked,
3595+
ArrayRef<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>> Checked,
35933596
SanitizerHandler CheckHandler, ArrayRef<llvm::Constant *> StaticArgs,
35943597
ArrayRef<llvm::Value *> DynamicArgs) {
35953598
assert(IsSanitizerScope);
@@ -3715,8 +3718,9 @@ void CodeGenFunction::EmitCheck(
37153718
}
37163719

37173720
void CodeGenFunction::EmitCfiSlowPathCheck(
3718-
SanitizerMask Kind, llvm::Value *Cond, llvm::ConstantInt *TypeId,
3719-
llvm::Value *Ptr, ArrayRef<llvm::Constant *> StaticArgs) {
3721+
SanitizerKind::SanitizerOrdinal Ordinal, llvm::Value *Cond,
3722+
llvm::ConstantInt *TypeId, llvm::Value *Ptr,
3723+
ArrayRef<llvm::Constant *> StaticArgs) {
37203724
llvm::BasicBlock *Cont = createBasicBlock("cfi.cont");
37213725

37223726
llvm::BasicBlock *CheckBB = createBasicBlock("cfi.slowpath");
@@ -3728,7 +3732,7 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
37283732

37293733
EmitBlock(CheckBB);
37303734

3731-
bool WithDiag = !CGM.getCodeGenOpts().SanitizeTrap.has(Kind);
3735+
bool WithDiag = !CGM.getCodeGenOpts().SanitizeTrap.has(Ordinal);
37323736

37333737
llvm::CallInst *CheckCall;
37343738
llvm::FunctionCallee SlowPathFn;
@@ -3860,22 +3864,23 @@ void CodeGenFunction::EmitCfiCheckFail() {
38603864
{Addr, AllVtables}),
38613865
IntPtrTy);
38623866

3863-
const std::pair<int, SanitizerMask> CheckKinds[] = {
3864-
{CFITCK_VCall, SanitizerKind::CFIVCall},
3865-
{CFITCK_NVCall, SanitizerKind::CFINVCall},
3866-
{CFITCK_DerivedCast, SanitizerKind::CFIDerivedCast},
3867-
{CFITCK_UnrelatedCast, SanitizerKind::CFIUnrelatedCast},
3868-
{CFITCK_ICall, SanitizerKind::CFIICall}};
3869-
3870-
SmallVector<std::pair<llvm::Value *, SanitizerMask>, 5> Checks;
3871-
for (auto CheckKindMaskPair : CheckKinds) {
3872-
int Kind = CheckKindMaskPair.first;
3873-
SanitizerMask Mask = CheckKindMaskPair.second;
3867+
const std::pair<int, SanitizerKind::SanitizerOrdinal> CheckKinds[] = {
3868+
{CFITCK_VCall, SanitizerKind::SO_CFIVCall},
3869+
{CFITCK_NVCall, SanitizerKind::SO_CFINVCall},
3870+
{CFITCK_DerivedCast, SanitizerKind::SO_CFIDerivedCast},
3871+
{CFITCK_UnrelatedCast, SanitizerKind::SO_CFIUnrelatedCast},
3872+
{CFITCK_ICall, SanitizerKind::SO_CFIICall}};
3873+
3874+
SmallVector<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>, 5>
3875+
Checks;
3876+
for (auto CheckKindOrdinalPair : CheckKinds) {
3877+
int Kind = CheckKindOrdinalPair.first;
3878+
SanitizerKind::SanitizerOrdinal Ordinal = CheckKindOrdinalPair.second;
38743879
llvm::Value *Cond =
38753880
Builder.CreateICmpNE(CheckKind, llvm::ConstantInt::get(Int8Ty, Kind));
3876-
if (CGM.getLangOpts().Sanitize.has(Mask))
3877-
EmitCheck(std::make_pair(Cond, Mask), SanitizerHandler::CFICheckFail, {},
3878-
{Data, Addr, ValidVtable});
3881+
if (CGM.getLangOpts().Sanitize.has(Ordinal))
3882+
EmitCheck(std::make_pair(Cond, Ordinal), SanitizerHandler::CFICheckFail,
3883+
{}, {Data, Addr, ValidVtable});
38793884
else
38803885
EmitTrapCheck(Cond, SanitizerHandler::CFICheckFail);
38813886
}
@@ -3890,7 +3895,7 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) {
38903895
if (SanOpts.has(SanitizerKind::Unreachable)) {
38913896
SanitizerScope SanScope(this);
38923897
EmitCheck(std::make_pair(static_cast<llvm::Value *>(Builder.getFalse()),
3893-
SanitizerKind::Unreachable),
3898+
SanitizerKind::SO_Unreachable),
38943899
SanitizerHandler::BuiltinUnreachable,
38953900
EmitCheckSourceLocation(Loc), {});
38963901
}
@@ -6054,7 +6059,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
60546059
Builder.CreateICmpEQ(CalleeTypeHash, TypeHash);
60556060
llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getBeginLoc()),
60566061
EmitCheckTypeDescriptor(CalleeType)};
6057-
EmitCheck(std::make_pair(CalleeTypeHashMatch, SanitizerKind::Function),
6062+
EmitCheck(std::make_pair(CalleeTypeHashMatch, SanitizerKind::SO_Function),
60586063
SanitizerHandler::FunctionTypeMismatch, StaticData,
60596064
{CalleePtr});
60606065

@@ -6091,10 +6096,10 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
60916096
EmitCheckTypeDescriptor(QualType(FnType, 0)),
60926097
};
60936098
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
6094-
EmitCfiSlowPathCheck(SanitizerKind::CFIICall, TypeTest, CrossDsoTypeId,
6099+
EmitCfiSlowPathCheck(SanitizerKind::SO_CFIICall, TypeTest, CrossDsoTypeId,
60956100
CalleePtr, StaticData);
60966101
} else {
6097-
EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIICall),
6102+
EmitCheck(std::make_pair(TypeTest, SanitizerKind::SO_CFIICall),
60986103
SanitizerHandler::CFICheckFail, StaticData,
60996104
{CalleePtr, llvm::UndefValue::get(IntPtrTy)});
61006105
}

0 commit comments

Comments
 (0)