[clang] 5916903 - [clang] Fix crash when #embed data does not fit into an array (#129567)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 5 02:04:56 PST 2025
Author: Mariya Podchishchaeva
Date: 2025-03-05T11:04:52+01:00
New Revision: 59169036ca0e064612886713d609873f776e85db
URL: https://github.com/llvm/llvm-project/commit/59169036ca0e064612886713d609873f776e85db
DIFF: https://github.com/llvm/llvm-project/commit/59169036ca0e064612886713d609873f776e85db.diff
LOG: [clang] Fix crash when #embed data does not fit into an array (#129567)
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 https://github.com/llvm/llvm-project/issues/128987
Added:
clang/test/CodeGen/excess-embed-data.c
clang/test/Sema/excess-embed-data.c
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaInit.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5098e5e983103..38111db3e6919 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -243,6 +243,8 @@ Bug Fixes in This Version
when it can affect template argument deduction (#GH122306).
- Fix crash on code completion of function calls involving partial order of function templates
(#GH125500).
+- Fixed clang crash when #embed data does not fit into an array
+ (#GH128987).
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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..9143125ba2398
--- /dev/null
+++ b/clang/test/CodeGen/excess-embed-data.c
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -std=c23 -emit-llvm -triple x86_64 %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 at -1{{excess elements in array initializer}}
+ // cpp-error at -2{{excess elements in array initializer}}
+};
+ int b[8] = {
+#embed __FILE__
+ // c-warning at -1{{excess elements in array initializer}}
+ // cpp-error at -2{{excess elements in array initializer}}
+};
+ int c[3000] = {x, x, x, x, x, x,
+#embed __FILE__
+ };
+ char d[3] = {
+#embed __FILE__
+ // c-warning at -1{{initializer-string for char array is too long}}
+ // cpp-error at -2{{initializer-string for char array is too long}}
+ };
+
+char e[3000] = { 1,
+#embed __FILE__
+};
+
+struct S s = {
+#embed __FILE__
+ // c-warning at -1{{excess elements in struct initializer}}
+ // cpp-error at -2{{excess elements in struct initializer}}
+ , x
+};
+
+struct S1 s1 = {
+#embed __FILE__
+ // c-warning at -1{{excess elements in struct initializer}}
+ // cpp-error at -2{{excess elements in struct initializer}}
+ , x
+};
+}
More information about the cfe-commits
mailing list