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

Reply via email to