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
