Skip to content

[clang]Fix Handle structs exceeding 1EB size limit #146032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

Karthikdhondi
Copy link
Contributor

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

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jun 27, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 27, 2025

@llvm/pr-subscribers-clang

Author: kd0608 (Karthikdhondi)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/146032.diff

4 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticASTKinds.td (+2)
  • (modified) clang/lib/AST/RecordLayoutBuilder.cpp (+7)
  • (added) clang/test/AST/absurdly_big_struct.cpp (+12)
  • (modified) clang/test/Sema/offsetof-64.c (+2-2)
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}}

Copy link

github-actions bot commented Jun 27, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@Karthikdhondi Karthikdhondi force-pushed the handle-absurdly-large-structs branch from 49fcccd to 45fb5d7 Compare June 27, 2025 16:45
Copy link
Collaborator

@rnk rnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good!

@Karthikdhondi
Copy link
Contributor Author

Thanks, looks good!

Thanks for the review.

@Karthikdhondi Karthikdhondi merged commit a6339d0 into llvm:main Jul 1, 2025
7 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 1, 2025

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building clang at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/25751

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Python/Crashlog/interactive_crashlog_invalid_target.test (3056 of 3067)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/watchpoint_callback.test (3057 of 3067)
UNSUPPORTED: lldb-shell :: Register/loongarch64-gp-read.test (3058 of 3067)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/breakpoint_callback.test (3059 of 3067)
UNSUPPORTED: lldb-shell :: Process/Windows/exception_access_violation.cpp (3060 of 3067)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/command_script_import.test (3061 of 3067)
UNSUPPORTED: lldb-shell :: SymbolFile/PDB/udt-layout.test (3062 of 3067)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/independent_state.test (3063 of 3067)
PASS: lldb-api :: terminal/TestEditlineCompletions.py (3064 of 3067)
UNRESOLVED: lldb-api :: tools/lldb-dap/launch/TestDAP_launch.py (3065 of 3067)
******************** TEST 'lldb-api :: tools/lldb-dap/launch/TestDAP_launch.py' FAILED ********************
Script:
--
/usr/bin/python3 /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./lib --env LLVM_INCLUDE_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/include --env LLVM_TOOLS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./bin --arch x86_64 --build-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex --lldb-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/lldb --compiler /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/clang --dsymutil /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./bin --lldb-obj-root /home/worker/2.0.1/lldb-x86_64-debian/build/tools/lldb --lldb-libs-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./lib --cmake-build-type Release -t /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/launch -p TestDAP_launch.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision a6339d0e5854b38fb8d9ec28974e129fdd0961f0)
  clang revision a6339d0e5854b38fb8d9ec28974e129fdd0961f0
  llvm revision a6339d0e5854b38fb8d9ec28974e129fdd0961f0
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
Change dir to: /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/launch
runCmd: settings clear --all

output: 

runCmd: settings set symbols.enable-external-lookup false

output: 

runCmd: settings set target.inherit-tcc true

output: 

runCmd: settings set target.disable-aslr false

output: 

runCmd: settings set target.detach-on-error false

output: 

runCmd: settings set target.auto-apply-fixits false

rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
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. llvm#60272
rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
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. llvm#60272
@Karthikdhondi Karthikdhondi deleted the handle-absurdly-large-structs branch July 2, 2025 04:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants