https://github.com/Karthikdhondi created https://github.com/llvm/llvm-project/pull/146032
When declaring multiple arrays of 1 ExaByte in a struct, the offset can exceed 2EB, causing incorrect struct size reporting (only 1EB). This fix ensures an error is thrown, preventing the generation of incorrect assembly. #60272 >From c6bf84fd57c550b1c160c4497b0de2f2db87c31f Mon Sep 17 00:00:00 2001 From: Karthikdhondi <karthik.dho...@gmail.com> Date: Fri, 27 Jun 2025 11:43:31 +0530 Subject: [PATCH] Fix: Handle structs exceeding 1EB size limit --- clang/include/clang/Basic/DiagnosticASTKinds.td | 2 ++ clang/lib/AST/RecordLayoutBuilder.cpp | 7 +++++++ clang/test/AST/absurdly_big_struct.cpp | 12 ++++++++++++ clang/test/Sema/offsetof-64.c | 4 ++-- 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 clang/test/AST/absurdly_big_struct.cpp diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index d2cd86d05d55a..e3be4ab47633d 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -999,6 +999,8 @@ def note_module_odr_violation_mismatch_decl_unknown : Note< "different friend declaration|different function template|different method|" "different instance variable|different property|another unexpected decl}2">; +def err_struct_too_large : Error< + "structure '%0' is too large, which exceeds maximum allowed size of %1 bytes">; def remark_sanitize_address_insert_extra_padding_accepted : Remark< "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader, diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index aacc079f2521d..f6a4f76bcc7f6 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -3463,6 +3463,13 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { ASTRecordLayouts[D] = NewEntry; + constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60; + CharUnits StructSize = NewEntry->getSize(); + if (static_cast<uint64_t>(StructSize.getQuantity()) >= MaxStructSizeInBytes) { + getDiagnostics().Report(D->getLocation(), diag::err_struct_too_large) + << D->getName() << MaxStructSizeInBytes; + } + if (getLangOpts().DumpRecordLayouts) { llvm::outs() << "\n*** Dumping AST Record Layout\n"; DumpRecordLayout(D, llvm::outs(), getLangOpts().DumpRecordLayoutsSimple); diff --git a/clang/test/AST/absurdly_big_struct.cpp b/clang/test/AST/absurdly_big_struct.cpp new file mode 100644 index 0000000000000..04ac4d7ef6b74 --- /dev/null +++ b/clang/test/AST/absurdly_big_struct.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-linux-gnu + +struct a { // expected-error {{structure 'a' is too large, which exceeds maximum allowed size of 1152921504606846976 bytes}} + char x[1ull<<60]; + char x2[1ull<<60]; +}; + +a z[1]; +long long x() { return sizeof(a); } +long long x2() { return sizeof(a::x); } +long long x3() { return sizeof(a::x2); } +long long x4() { return sizeof(z); } diff --git a/clang/test/Sema/offsetof-64.c b/clang/test/Sema/offsetof-64.c index 8ffc3af985880..692698fe39e00 100644 --- a/clang/test/Sema/offsetof-64.c +++ b/clang/test/Sema/offsetof-64.c @@ -2,7 +2,7 @@ // PR15216 // Don't crash when taking computing the offset of structs with large arrays. -const unsigned long Size = (1l << 60); +const unsigned long Size = (1l << 58); struct Chunk1 { char padding[Size]; // expected-warning {{folded to constant}} @@ -10,7 +10,7 @@ struct Chunk1 { char data; }; -int test1 = __builtin_offsetof(struct Chunk1, data); +unsigned long test1 = __builtin_offsetof(struct Chunk1, data); struct Chunk2 { char padding[Size][Size][Size]; // expected-error {{array is too large}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits