[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