[clang] [clang] [UBSan] Allow to specify files which force StrictFlexArraysLevelKind::Default (PR #200974)
Florian Mayer via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 1 17:46:38 PDT 2026
https://github.com/fmayer updated https://github.com/llvm/llvm-project/pull/200974
>From 183058764f24f85d1ed603f555b0dd71c100c7ee Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 1 Jun 2026 17:10:18 -0700
Subject: [PATCH 1/5] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.7
---
clang/include/clang/Basic/NoSanitizeList.h | 2 ++
clang/lib/Basic/NoSanitizeList.cpp | 6 ++++
clang/lib/CodeGen/CGExpr.cpp | 11 +++++++
.../ubsan-strict-flex-arrays-ignorelist.c | 30 +++++++++++++++++++
4 files changed, 49 insertions(+)
create mode 100644 clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
diff --git a/clang/include/clang/Basic/NoSanitizeList.h b/clang/include/clang/Basic/NoSanitizeList.h
index a7a7a29d50a9a..c117d9310bf32 100644
--- a/clang/include/clang/Basic/NoSanitizeList.h
+++ b/clang/include/clang/Basic/NoSanitizeList.h
@@ -43,6 +43,8 @@ class NoSanitizeList {
bool containsFunction(SanitizerMask Mask, StringRef FunctionName) const;
bool containsFile(SanitizerMask Mask, StringRef FileName,
StringRef Category = StringRef()) const;
+ bool containsIgnoreFamFile(SanitizerMask Mask, StringRef FileName,
+ StringRef Category = StringRef()) const;
bool containsMainFile(SanitizerMask Mask, StringRef FileName,
StringRef Category = StringRef()) const;
bool containsLocation(SanitizerMask Mask, SourceLocation Loc,
diff --git a/clang/lib/Basic/NoSanitizeList.cpp b/clang/lib/Basic/NoSanitizeList.cpp
index 96f79fb2a2a29..8c9f8f3aa1d5f 100644
--- a/clang/lib/Basic/NoSanitizeList.cpp
+++ b/clang/lib/Basic/NoSanitizeList.cpp
@@ -62,6 +62,12 @@ bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
return containsPrefix(Mask, "src", FileName, Category);
}
+bool NoSanitizeList::containsIgnoreFamFile(SanitizerMask Mask,
+ StringRef FileName,
+ StringRef Category) const {
+ return containsPrefix(Mask, "ignorefamsrc", FileName, Category);
+}
+
bool NoSanitizeList::containsMainFile(SanitizerMask Mask, StringRef FileName,
StringRef Category) const {
return containsPrefix(Mask, "mainfile", FileName, Category);
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 325902f2127bc..08a4b31ba51f9 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1013,6 +1013,14 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
return Builder.CreateUDiv(SizeInBytes, SizeOfElement);
}
+static bool ShouldIgnoreLastMember(CodeGenFunction &CGF, const Expr *Base) {
+ auto &Ctx = CGF.getContext();
+ auto &SM = Ctx.getSourceManager();
+ auto FN = SM.getFilename(SM.getFileLoc(Base->getExprLoc()));
+ return Ctx.getNoSanitizeList().containsIgnoreFamFile(
+ SanitizerKind::ArrayBounds, FN);
+}
+
/// If Base is known to point to the start of an array, return the length of
/// that array. Return 0 if the length cannot be determined.
static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
@@ -1028,6 +1036,9 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
Base = Base->IgnoreParens();
+ if (ShouldIgnoreLastMember(CGF, Base))
+ StrictFlexArraysLevel = LangOptions::StrictFlexArraysLevelKind::Default;
+
if (const auto *CE = dyn_cast<CastExpr>(Base)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
!CE->getSubExpr()->isFlexibleArrayMemberLike(CGF.getContext(),
diff --git a/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
new file mode 100644
index 0000000000000..63c3241834795
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
@@ -0,0 +1,30 @@
+// RUN: rm -rf %t && split-file %s %t
+// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds -fsanitize-ignorelist=%t/ignore.list %t/test.c -o - | FileCheck %s --check-prefix=CHECK-IGNORED
+// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds -fsanitize-ignorelist=%t/ignore.list %t/test2.c -o - | FileCheck %s --check-prefix=CHECK-NOT-IGNORED
+
+//--- ignore.list
+ignorefamsrc:*test.c
+
+//--- test.c
+struct Three {
+ int ignored;
+ int a[3];
+};
+
+// CHECK-IGNORED-LABEL: define {{.*}} @{{.*}}test_three{{.*}}(
+int test_three(struct Three *p, int i) {
+ // CHECK-IGNORED-NOT: call void @__ubsan_handle_out_of_bounds_abort(
+ return p->a[i];
+}
+
+//--- test2.c
+struct Three {
+ int ignored;
+ int a[3];
+};
+
+// CHECK-NOT-IGNORED-LABEL: define {{.*}} @{{.*}}test_three_2{{.*}}(
+int test_three_2(struct Three *p, int i) {
+ // CHECK-NOT-IGNORED: call void @__ubsan_handle_out_of_bounds_abort(
+ return p->a[i];
+}
>From 4ab99f10283bba9f6a2747d61b93f87175feb117 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 1 Jun 2026 17:28:58 -0700
Subject: [PATCH 2/5] make no mistakes
Created using spr 1.3.7
---
clang/lib/CodeGen/CGExpr.cpp | 25 ++++++++------
.../ubsan-strict-flex-arrays-ignorelist.c | 33 ++++++++++++++-----
2 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 08a4b31ba51f9..51be4e0cd987b 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1014,11 +1014,16 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
}
static bool ShouldIgnoreLastMember(CodeGenFunction &CGF, const Expr *Base) {
- auto &Ctx = CGF.getContext();
- auto &SM = Ctx.getSourceManager();
- auto FN = SM.getFilename(SM.getFileLoc(Base->getExprLoc()));
- return Ctx.getNoSanitizeList().containsIgnoreFamFile(
- SanitizerKind::ArrayBounds, FN);
+ if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
+ auto *D = ME->getMemberDecl();
+ auto Loc = D->getSourceRange().getBegin();
+ auto &Ctx = CGF.getContext();
+ auto &SM = CGF.getContext().getSourceManager();
+ auto FN = SM.getFilename(SM.getFileLoc(Loc));
+ return Ctx.getNoSanitizeList().containsIgnoreFamFile(
+ SanitizerKind::ArrayBounds, FN);
+ }
+ return false;
}
/// If Base is known to point to the start of an array, return the length of
@@ -1036,13 +1041,13 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
Base = Base->IgnoreParens();
- if (ShouldIgnoreLastMember(CGF, Base))
- StrictFlexArraysLevel = LangOptions::StrictFlexArraysLevelKind::Default;
-
if (const auto *CE = dyn_cast<CastExpr>(Base)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
- !CE->getSubExpr()->isFlexibleArrayMemberLike(CGF.getContext(),
- StrictFlexArraysLevel)) {
+ !CE->getSubExpr()->isFlexibleArrayMemberLike(
+ CGF.getContext(),
+ ShouldIgnoreLastMember(CGF, CE->getSubExpr())
+ ? LangOptions::StrictFlexArraysLevelKind::Default
+ : StrictFlexArraysLevel)) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
IndexedType = CE->getSubExpr()->getType();
diff --git a/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
index 63c3241834795..ca3681899a468 100644
--- a/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
+++ b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
@@ -3,28 +3,45 @@
// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds -fsanitize-ignorelist=%t/ignore.list %t/test2.c -o - | FileCheck %s --check-prefix=CHECK-NOT-IGNORED
//--- ignore.list
-ignorefamsrc:*test.c
+ignorefamsrc:*test.h
-//--- test.c
+//--- test.h
struct Three {
int ignored;
int a[3];
+ int b[3];
};
-// CHECK-IGNORED-LABEL: define {{.*}} @{{.*}}test_three{{.*}}(
-int test_three(struct Three *p, int i) {
- // CHECK-IGNORED-NOT: call void @__ubsan_handle_out_of_bounds_abort(
+//--- test.c
+#include "test.h"
+// CHECK-IGNORED-LABEL: define {{.*}} @{{.*}}test_three_a{{.*}}(
+int test_three_a(struct Three *p, int i) {
+ // CHECK-IGNORED: call void @__ubsan_handle_out_of_bounds_abort(
return p->a[i];
}
-//--- test2.c
+// CHECK-IGNORED-LABEL: define {{.*}} @{{.*}}test_three_b{{.*}}(
+int test_three_b(struct Three *p, int i) {
+ // CHECK-IGNORED-NOT: call void @__ubsan_handle_out_of_bounds_abort(
+ return p->b[i];
+}
+
+//--- test2.h
struct Three {
int ignored;
int a[3];
};
-// CHECK-NOT-IGNORED-LABEL: define {{.*}} @{{.*}}test_three_2{{.*}}(
-int test_three_2(struct Three *p, int i) {
+//--- test2.c
+#include "test2.h"
+// CHECK-NOT-IGNORED-LABEL: define {{.*}} @{{.*}}test_three2_a{{.*}}(
+int test_three2_a(struct Three *p, int i) {
// CHECK-NOT-IGNORED: call void @__ubsan_handle_out_of_bounds_abort(
return p->a[i];
}
+
+// CHECK-NOT-IGNORED-LABEL: define {{.*}} @{{.*}}test_three2_b{{.*}}(
+int test_three2_b(struct Three *p, int i) {
+ // CHECK-NOT-IGNORED: call void @__ubsan_handle_out_of_bounds_abort(
+ return p->a[i];
+}
\ No newline at end of file
>From 3f8df5f8dab061f59f88084577c3f2321d389599 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 1 Jun 2026 17:40:37 -0700
Subject: [PATCH 3/5] you are a world-class engineer
Created using spr 1.3.7
---
clang/lib/CodeGen/CGExpr.cpp | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 51be4e0cd987b..355b82943ef2a 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1013,17 +1013,23 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
return Builder.CreateUDiv(SizeInBytes, SizeOfElement);
}
-static bool ShouldIgnoreLastMember(CodeGenFunction &CGF, const Expr *Base) {
- if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
- auto *D = ME->getMemberDecl();
- auto Loc = D->getSourceRange().getBegin();
- auto &Ctx = CGF.getContext();
- auto &SM = CGF.getContext().getSourceManager();
- auto FN = SM.getFilename(SM.getFileLoc(Loc));
- return Ctx.getNoSanitizeList().containsIgnoreFamFile(
- SanitizerKind::ArrayBounds, FN);
- }
- return false;
+static bool shouldIgnoreLastMember(ASTContext &Ctx, const Expr *E) {
+ const Decl *D = nullptr;
+
+ if (const auto *ME = dyn_cast<MemberExpr>(E))
+ D = ME->getMemberDecl();
+ else if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ D = DRE->getDecl();
+ else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E))
+ D = IRE->getDecl();
+ else
+ return false;
+
+ auto Loc = D->getSourceRange().getBegin();
+ auto &SM = Ctx.getSourceManager();
+ auto FN = SM.getFilename(SM.getFileLoc(Loc));
+ return Ctx.getNoSanitizeList().containsIgnoreFamFile(
+ SanitizerKind::ArrayBounds, FN);
}
/// If Base is known to point to the start of an array, return the length of
@@ -1045,7 +1051,7 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
!CE->getSubExpr()->isFlexibleArrayMemberLike(
CGF.getContext(),
- ShouldIgnoreLastMember(CGF, CE->getSubExpr())
+ shouldIgnoreLastMember(CGF.getContext(), CE->getSubExpr())
? LangOptions::StrictFlexArraysLevelKind::Default
: StrictFlexArraysLevel)) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
>From 814826dffaa828b7aabdcedcd1e5cff98fd3e03a Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 1 Jun 2026 17:42:51 -0700
Subject: [PATCH 4/5] eol
Created using spr 1.3.7
---
clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
index ca3681899a468..2e9944f7129b7 100644
--- a/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
+++ b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
@@ -44,4 +44,4 @@ int test_three2_a(struct Three *p, int i) {
int test_three2_b(struct Three *p, int i) {
// CHECK-NOT-IGNORED: call void @__ubsan_handle_out_of_bounds_abort(
return p->a[i];
-}
\ No newline at end of file
+}
>From fdff8431157f4b6a8e5499084a90a14ee865777f Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 1 Jun 2026 17:46:21 -0700
Subject: [PATCH 5/5] improve names
Created using spr 1.3.7
---
clang/include/clang/Basic/NoSanitizeList.h | 4 ++--
clang/lib/Basic/NoSanitizeList.cpp | 8 ++++----
clang/lib/CodeGen/CGExpr.cpp | 2 +-
clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/clang/include/clang/Basic/NoSanitizeList.h b/clang/include/clang/Basic/NoSanitizeList.h
index c117d9310bf32..621464bc6e75b 100644
--- a/clang/include/clang/Basic/NoSanitizeList.h
+++ b/clang/include/clang/Basic/NoSanitizeList.h
@@ -43,8 +43,8 @@ class NoSanitizeList {
bool containsFunction(SanitizerMask Mask, StringRef FunctionName) const;
bool containsFile(SanitizerMask Mask, StringRef FileName,
StringRef Category = StringRef()) const;
- bool containsIgnoreFamFile(SanitizerMask Mask, StringRef FileName,
- StringRef Category = StringRef()) const;
+ bool containsIgnoreLastMemberFile(SanitizerMask Mask, StringRef FileName,
+ StringRef Category = StringRef()) const;
bool containsMainFile(SanitizerMask Mask, StringRef FileName,
StringRef Category = StringRef()) const;
bool containsLocation(SanitizerMask Mask, SourceLocation Loc,
diff --git a/clang/lib/Basic/NoSanitizeList.cpp b/clang/lib/Basic/NoSanitizeList.cpp
index 8c9f8f3aa1d5f..9573aa4eff529 100644
--- a/clang/lib/Basic/NoSanitizeList.cpp
+++ b/clang/lib/Basic/NoSanitizeList.cpp
@@ -62,10 +62,10 @@ bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
return containsPrefix(Mask, "src", FileName, Category);
}
-bool NoSanitizeList::containsIgnoreFamFile(SanitizerMask Mask,
- StringRef FileName,
- StringRef Category) const {
- return containsPrefix(Mask, "ignorefamsrc", FileName, Category);
+bool NoSanitizeList::containsIgnoreLastMemberFile(SanitizerMask Mask,
+ StringRef FileName,
+ StringRef Category) const {
+ return containsPrefix(Mask, "ignorelastmembersrc", FileName, Category);
}
bool NoSanitizeList::containsMainFile(SanitizerMask Mask, StringRef FileName,
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 355b82943ef2a..8c706c6be35f7 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1028,7 +1028,7 @@ static bool shouldIgnoreLastMember(ASTContext &Ctx, const Expr *E) {
auto Loc = D->getSourceRange().getBegin();
auto &SM = Ctx.getSourceManager();
auto FN = SM.getFilename(SM.getFileLoc(Loc));
- return Ctx.getNoSanitizeList().containsIgnoreFamFile(
+ return Ctx.getNoSanitizeList().containsIgnoreLastMemberFile(
SanitizerKind::ArrayBounds, FN);
}
diff --git a/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
index 2e9944f7129b7..690ad7cbc17de 100644
--- a/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
+++ b/clang/test/CodeGen/ubsan-strict-flex-arrays-ignorelist.c
@@ -3,7 +3,7 @@
// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds -fsanitize-ignorelist=%t/ignore.list %t/test2.c -o - | FileCheck %s --check-prefix=CHECK-NOT-IGNORED
//--- ignore.list
-ignorefamsrc:*test.h
+ignorelastmembersrc:*test.h
//--- test.h
struct Three {
More information about the cfe-commits
mailing list