-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Fix crash when #embed data does not fit into an array #129567
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
Conversation
Tune SemaInit code handling #embed to take into account how many array elements remains to initialize. Also issue a warning/error message when the array/struct is at the end but there is still #embed data left. Fixes llvm#128987
@llvm/pr-subscribers-clang Author: Mariya Podchishchaeva (Fznamznon) ChangesTune SemaInit code handling #embed to take into account how many array elements remains to initialize. Fixes #128987 Full diff: https://github.com/llvm/llvm-project/pull/129567.diff 3 Files Affected:
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 86f5a5c1d4434..56ec33fe37bf3 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -519,12 +519,13 @@ class InitListChecker {
uint64_t ElsCount = 1;
// Otherwise try to fill whole array with embed data.
if (Entity.getKind() == InitializedEntity::EK_ArrayElement) {
+ unsigned ArrIndex = Entity.getElementIndex();
auto *AType =
SemaRef.Context.getAsArrayType(Entity.getParent()->getType());
assert(AType && "expected array type when initializing array");
ElsCount = Embed->getDataElementCount();
if (const auto *CAType = dyn_cast<ConstantArrayType>(AType))
- ElsCount = std::min(CAType->getSize().getZExtValue(),
+ ElsCount = std::min(CAType->getSize().getZExtValue() - ArrIndex,
ElsCount - CurEmbedIndex);
if (ElsCount == Embed->getDataElementCount()) {
CurEmbed = nullptr;
@@ -1317,7 +1318,7 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
return;
// Don't complain for incomplete types, since we'll get an error elsewhere.
- if (Index < IList->getNumInits() && !T->isIncompleteType()) {
+ if ((Index < IList->getNumInits() || CurEmbed) && !T->isIncompleteType()) {
// We have leftover initializers
bool ExtraInitsIsError = SemaRef.getLangOpts().CPlusPlus ||
(SemaRef.getLangOpts().OpenCL && T->isVectorType());
@@ -2180,6 +2181,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
InitializedEntity ElementEntity = InitializedEntity::InitializeElement(
SemaRef.Context, StructuredIndex, Entity);
+ ElementEntity.setElementIndex(elementIndex.getExtValue());
unsigned EmbedElementIndexBeforeInit = CurEmbedIndex;
// Check this element.
diff --git a/clang/test/CodeGen/excess-embed-data.c b/clang/test/CodeGen/excess-embed-data.c
new file mode 100644
index 0000000000000..4303cd80b8c5c
--- /dev/null
+++ b/clang/test/CodeGen/excess-embed-data.c
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -std=c23 -emit-llvm %s -o - | FileCheck %s
+
+struct S {
+ int arr[3];
+};
+
+struct S1 {
+ struct S s;
+};
+
+// CHECK: @[[BConst:.*]] = private unnamed_addr constant [2 x i32] [i32 47, i32 47]
+// CHECK: @[[DConst:.*]] = private unnamed_addr constant [2 x i8] c"//"
+// CHECK: @[[SConst:.*]] = private unnamed_addr constant %struct.S { [3 x i32] [i32 47, i32 47, i32 32] }
+// CHECK: @[[S1Const:.*]] = private unnamed_addr constant %struct.S1 { %struct.S { [3 x i32] [i32 47, i32 47, i32 32] } }
+
+void cases(int x) {
+ int a[3] = {x, x,
+#embed __FILE__
+ };
+
+ int b[2] = {
+#embed __FILE__
+ };
+
+ char d[2] = {
+#embed __FILE__
+ };
+
+ struct S s = {
+#embed __FILE__
+ , x
+ };
+
+ struct S1 s1 = {
+#embed __FILE__
+ , x
+ };
+}
+// CHECK: define dso_local void @cases(i32 noundef %[[X:.*]])
+// CHECK: %[[A:.*]] = alloca [3 x i32]
+// CHECK: %[[B:.*]] = alloca [2 x i32]
+// CHECK: %[[D:.*]] = alloca [2 x i8]
+// CHECK: %[[S:.*]] = alloca %struct.S
+// CHECK: %[[S1:.*]] = alloca %struct.S1
+// CHECK: %[[LX:.*]] = load i32, ptr %[[X]].addr
+// CHECK: store i32 %[[LX]], ptr %[[A]]
+// CHECK: %[[GEP1:.*]] = getelementptr inbounds i32, ptr %[[A]], i64 1
+// CHECK: %[[LX1:.*]] = load i32, ptr %[[X]].addr
+// CHECK: store i32 %1, ptr %arrayinit.element
+// CHECK: %[[GEP1:.*]] = getelementptr inbounds i32, ptr %[[A]], i64 2
+// CHECK: store i32 47, ptr %[[GEP1]]
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[B]], ptr align 4 @[[BConst]], i64 8, i1 false)
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[D]], ptr align 1 @[[DConst]], i64 2, i1 false)
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[S]], ptr align 4 @[[SConst]], i64 12, i1 false)
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[S1]], ptr align 4 @[[S1Const]], i64 12, i1 false)
diff --git a/clang/test/Sema/excess-embed-data.c b/clang/test/Sema/excess-embed-data.c
new file mode 100644
index 0000000000000..d5b84921abc89
--- /dev/null
+++ b/clang/test/Sema/excess-embed-data.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify=c %s
+// RUN: %clang_cc1 -fsyntax-only -verify=cpp -x c++ -Wno-c23-extensions %s
+
+
+struct S {
+ int arr[3];
+};
+
+struct S1 {
+ struct S s;
+};
+
+void cases(int x) {
+ int a[8] = {x, x, x, x, x, x,
+#embed __FILE__
+ // c-warning@-1{{excess elements in array initializer}}
+ // cpp-error@-2{{excess elements in array initializer}}
+};
+ int b[8] = {
+#embed __FILE__
+ // c-warning@-1{{excess elements in array initializer}}
+ // cpp-error@-2{{excess elements in array initializer}}
+};
+ int c[3000] = {x, x, x, x, x, x,
+#embed __FILE__
+ };
+ char d[3] = {
+#embed __FILE__
+ // c-warning@-1{{initializer-string for char array is too long}}
+ // cpp-error@-2{{initializer-string for char array is too long}}
+ };
+
+char e[3000] = { 1,
+#embed __FILE__
+};
+
+struct S s = {
+#embed __FILE__
+ // c-warning@-1{{excess elements in struct initializer}}
+ // cpp-error@-2{{excess elements in struct initializer}}
+ , x
+};
+
+struct S1 s1 = {
+#embed __FILE__
+ // c-warning@-1{{excess elements in struct initializer}}
+ // cpp-error@-2{{excess elements in struct initializer}}
+ , x
+};
+}
|
Thanks for the fix! |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/30/builds/16950 Here is the relevant piece of the build log for the reference
|
…29567) Tune SemaInit code handling #embed to take into account how many array elements remains to initialize. Also issue a warning/error message when the array/struct is at the end but there is still #embed data left. Fixes llvm#128987
Tune SemaInit code handling #embed to take into account how many array elements remains to initialize.
Also issue a warning/error message when the array/struct is at the end but there is still #embed data left.
Fixes #128987