Author: tobiichi3227
Date: 2026-08-12T11:21:29Z
New Revision: 8aaace9f6f0f0144c8c9bbe313eb95720c7c23cf

URL: 
https://github.com/llvm/llvm-project/commit/8aaace9f6f0f0144c8c9bbe313eb95720c7c23cf
DIFF: 
https://github.com/llvm/llvm-project/commit/8aaace9f6f0f0144c8c9bbe313eb95720c7c23cf.diff

LOG: [clang][Sema] Fix crash when checking scalar type with excess braces 
(#192471)

`InitListChecker::CheckScalarType()` crashed with multiple nested braces
in scalar initializers (e.g., `int v = {{}, {}, {}};`) due to
out-of-bounds access when retrieving diagnostic location from
uninitialized StructuredList.

Add bounds checking before `getInit(0)` access and add regression test

Fix #137845. Fix #69213. Fix #198767. Fix #207566. Fix #106180.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Sema/SemaInit.cpp
    clang/test/Sema/init.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index b5aa71119e4b7..9648ad429d040 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -397,6 +397,7 @@ features cannot lower the translation-unit ABI level;
 - Fixed a bug where `__func__`, `__PRETTY_FUNCTION__` and `__FUNCTION__` were 
not resolving to the proper function when inside a lambda return type 
(#GH211811)
 - Fixed USR generation for declarations whose signature mentions a class-type
   non-type template parameter. (#GH212351)
+- Fixed a crash when checking scalar type with excess braces. (#GH69213), 
(#GH137845), (#GH198767), (#GH207566), (#GH106180)
 - Fixed an assertion crash when instantiating a nested requirement with an 
invalid constraint. (#GH213575)
 - Clang now defines the GCC-compatible predefined macro `__SIG_ATOMIC_TYPE__`. 
(#GH213895)
 - Fixed a bug where a stray closing curley brace in an OpenMP/OpenACC pragma 
could cause pragma parsing issues when inside of a member function. (#GH214195)

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 09d9f1eabd058..fd00b1d02fa18 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -1362,26 +1362,31 @@ void InitListChecker::CheckExplicitInitList(const 
InitializedEntity &Entity,
   // Don't complain for incomplete types, since we'll get an error elsewhere.
   if ((Index < IList->getNumInits() || CurEmbed) && !T->isIncompleteType()) {
     // We have leftover initializers
+    Expr *ExtraInit =
+        Index < IList->getNumInits() ? IList->getInit(Index) : CurEmbed;
+    SourceLocation ExtraInitLoc =
+        ExtraInit ? ExtraInit->getBeginLoc() : IList->getEndLoc();
+    SourceRange ExtraInitRange =
+        ExtraInit ? ExtraInit->getSourceRange() : IList->getSourceRange();
     bool ExtraInitsIsError = SemaRef.getLangOpts().CPlusPlus ||
           (SemaRef.getLangOpts().OpenCL && T->isVectorType());
     hadError = ExtraInitsIsError;
     if (VerifyOnly) {
       return;
-    } else if (StructuredIndex == 1 &&
+    } else if (StructuredIndex == 1 && StructuredList->getNumInits() != 0 &&
+               StructuredList->getInit(0) &&
                IsStringInit(StructuredList->getInit(0), T, SemaRef.Context) ==
                    SIF_None) {
       unsigned DK =
           ExtraInitsIsError
               ? diag::err_excess_initializers_in_char_array_initializer
               : diag::ext_excess_initializers_in_char_array_initializer;
-      SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
-          << IList->getInit(Index)->getSourceRange();
+      SemaRef.Diag(ExtraInitLoc, DK) << ExtraInitRange;
     } else if (T->isSizelessBuiltinType()) {
       unsigned DK = ExtraInitsIsError
                         ? diag::err_excess_initializers_for_sizeless_type
                         : diag::ext_excess_initializers_for_sizeless_type;
-      SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
-          << T << IList->getInit(Index)->getSourceRange();
+      SemaRef.Diag(ExtraInitLoc, DK) << T << ExtraInitRange;
     } else {
       int initKind = T->isArrayType()    ? 0
                      : T->isVectorType() ? 1
@@ -1392,8 +1397,7 @@ void InitListChecker::CheckExplicitInitList(const 
InitializedEntity &Entity,
 
       unsigned DK = ExtraInitsIsError ? diag::err_excess_initializers
                                       : diag::ext_excess_initializers;
-      SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
-          << initKind << IList->getInit(Index)->getSourceRange();
+      SemaRef.Diag(ExtraInitLoc, DK) << initKind << ExtraInitRange;
     }
   }
 

diff  --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c
index cf3788bc21c93..32a0a94a8b8a6 100644
--- a/clang/test/Sema/init.c
+++ b/clang/test/Sema/init.c
@@ -204,3 +204,57 @@ union PR4517_u {
 const union PR4517_u u1 = {4.0f};
 const union PR4517_u u2 = u1; // no-warning
 const union PR4517_u u3 = {u1.y}; // expected-error {{initializer element is 
not a compile-time constant}}
+
+int PR192471_1 = {{}, {}, {}}; // expected-warning {{too many braces around 
scalar initializer}} expected-warning {{excess elements in scalar initializer}}
+char PR192471_2[] = {
+    "1110",
+#embed __FILE__ // expected-warning {{#embed is a C23 extension}} \
+                   expected-warning {{excess elements in char array 
initializer}}
+};
+char PR192471_3[1] = {
+#embed __FILE__ limit(1) // expected-warning {{#embed is a C23 extension}}
+, 49, 49, 49, 48 // expected-warning {{excess elements in array initializer}}
+};
+
+void PR192471_4(int *ptr) {
+  *ptr = (int){{}, // expected-warning {{too many braces around scalar 
initializer}}
+#embed __FILE__ limit(1) // expected-warning {{#embed is a C23 extension}} \
+                           expected-warning {{excess elements in scalar 
initializer}}
+  };
+}
+
+// GH137845
+struct GH137845_Data; // expected-note 2 {{forward declaration of 'struct 
GH137845_Data'}}
+double GH137845_swap(struct GH137845_Data *, struct GH137845_Data *);
+void GH137845(void) {
+  GH137845_swap(
+      (struct GH137845_Data[5]){{}, 1}, // expected-error {{array has 
incomplete element type 'struct GH137845_Data'}} \
+                                             expected-warning {{too many 
braces around scalar initializer}} \
+                                             expected-warning {{excess 
elements in scalar initializer}}
+      (struct GH137845_Data[5]){{}, 4}); // expected-error {{array has 
incomplete element type 'struct GH137845_Data'}} \
+                                              expected-warning {{too many 
braces around scalar initializer}} \
+                                              expected-warning {{excess 
elements in scalar initializer}}
+}
+
+// GH69213
+int GH69213_ptr;
+void GH69213(void) {
+  *GH69213_ptr = (int){{}, 0}; // expected-error {{indirection requires 
pointer operand ('int' invalid)}} \
+                                      expected-warning {{too many braces 
around scalar initializer}} \
+                                      expected-warning {{excess elements in 
scalar initializer}}
+}
+
+// GH198767
+void GH198767(void) {
+  static __thread static char buffer[128] = {{{}, 0}}; // expected-warning 
{{duplicate 'static' declaration specifier}} \
+                                                             expected-warning 
{{too many braces around scalar initializer}} \
+                                                             expected-warning 
{{excess elements in scalar initializer}}
+}
+
+struct GH207566 {};
+struct GH207566 **GH207566_s = {{}, NULL}; // expected-warning {{too many 
braces around scalar initializer}} \
+                                                 expected-warning {{excess 
elements in scalar initializer}}
+
+GH106180 = {{}, 1}; // expected-error {{type specifier missing, defaults to 
'int'; ISO C99 and later do not support implicit int}} \
+                           expected-warning {{too many braces around scalar 
initializer}} \
+                           expected-warning {{excess elements in scalar 
initializer}}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to