Skip to content

[UBSan] Move type:*=sanitize handling. #142006

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

Merged
merged 3 commits into from
May 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,8 +875,7 @@ ASTContext::insertCanonicalTemplateTemplateParmDeclInternal(
bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
const QualType &Ty) const {
std::string TyName = Ty.getUnqualifiedType().getAsString(getPrintingPolicy());
return NoSanitizeL->containsType(Mask, TyName) &&
!NoSanitizeL->containsType(Mask, TyName, "sanitize");
return NoSanitizeL->containsType(Mask, TyName);
}

TargetCXXABI::Kind ASTContext::getCXXABIKind() const {
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Basic/NoSanitizeList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ bool NoSanitizeList::containsGlobal(SanitizerMask Mask, StringRef GlobalName,

bool NoSanitizeList::containsType(SanitizerMask Mask, StringRef MangledTypeName,
StringRef Category) const {
return SSCL->inSection(Mask, "type", MangledTypeName, Category);
auto NoSan = SSCL->inSectionBlame(Mask, "type", MangledTypeName, Category);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this code pattern can be extracted into private helper and used across other prefixes.

Copy link
Member Author

@qinkunbao qinkunbao May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I had the same thought when I copied the code from "containsType" to "containsFile".

I am going to publish a followup PR to address the issue.

if (NoSan == llvm::SpecialCaseList::NotFound)
return false;
auto San = SSCL->inSectionBlame(Mask, "type", MangledTypeName, "sanitize");
return San == llvm::SpecialCaseList::NotFound || NoSan > San;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR looks good to me. Only quirk is NoSan > San. The autos slightly obscure the fact these are pair types. Thankfully, the FileIdx portion of the pair is properly mapped left-to-right alongside all the -fsanitize-ignorelist= arguments within SpecialCaseList::createInternal. This means we'll get the obvious behavior of most recent SCL file which is then further delineated by line number.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review. Given this part is going to be refactored in #142027 , I am going to merge this PR and change "auto" to "std::pair<unsigned, unsigned>" in #142027

}

bool NoSanitizeList::containsFunction(SanitizerMask Mask,
Expand Down
59 changes: 41 additions & 18 deletions clang/test/CodeGen/ubsan-type-ignorelist-category-2.test
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
// RUN: rm -rf %t
// RUN: split-file %s %t

// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-0.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-1.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-2.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-3.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-4.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-5.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-6.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-7.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s

// The same type can appear multiple times within an ignorelist. This is a test
// to make sure "=sanitize" has priority regardless of the order in which
// duplicate type entries appear. This is a precautionary measure; we would
// much rather eagerly sanitize than silently forgo sanitization.
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-0.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,SANITIZE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-1.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-2.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,SANITIZE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-3.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-4.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,SANITIZE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-5.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-6.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,SANITIZE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-7.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,IGNORE
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-8.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s --check-prefixes=CHECK,SANITIZE


// The same type can appear multiple times within an ignorelist. Any ``=sanitize`` type
// entries enable sanitizer instrumentation, even if it was ignored by entries before.
// If multiple entries match the source, than the latest entry takes the
// precedence.


//--- order-0.ignorelist
type:int
Expand All @@ -40,19 +43,39 @@ type:int=sanitize
type:in*

//--- order-6.ignorelist
type:int
type:int=sanitize
type:in*

//--- order-7.ignorelist
type:int
[{unsigned-integer-overflow,signed-integer-overflow}]
type:*
type:int=sanitize
type:i*t
type:*nt=sanitize
[{unsigned-integer-overflow,signed-integer-overflow}]
type:*
type:int
type:i*t=sanitize
type:*nt


//--- order-8.ignorelist
[{unsigned-integer-overflow,signed-integer-overflow}]
type:*
type:int
type:i*t=sanitize
type:*nt
[{unsigned-integer-overflow,signed-integer-overflow}]
type:*
type:int=sanitize
type:i*t
type:*nt=sanitize


//--- test.c
// CHECK-LABEL: @test
// CHECK-LABEL: define dso_local void @test
void test(int A) {
// CHECK: @llvm.sadd.with.overflow.i32
// IGNORE: %inc = add nsw
// SANITIZE: @llvm.sadd.with.overflow.i32
++A;
}