[clang] [Clang][Frontend] Fix fix-it size overflow in emitted .dia (PR #216075)
Nuri Amari via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 13 08:01:47 PDT 2026
https://github.com/NuriAmari created https://github.com/llvm/llvm-project/pull/216075
When fix-its are emitted into a .dia, we previously stored the fix-it text in a blob of arbitrary size, but the size of the text was stored in a separate 16 bit field. For really large fix-its, the size won't fit it those 16 bits, and the compiler crashes.
Switch to a variable length encoding of the fit-it size. This is similar to this issue:
https://github.com/llvm/llvm-project/commit/e26aea5b290165f3bccffab662a706d4a56f7540
We also remove a hard coded check in the clang library used to load .dia files that failed for fix-its whose size doesn't fit in 16 bits.
Generated with codex
>From d7d2b46e72051aa5780f6e5d61e2a635318edba7 Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Wed, 12 Aug 2026 13:51:18 -0700
Subject: [PATCH] [Frontend] Fix fix-it size overflow in emitted .dia
When fix-its are emitted into a .dia, we previously stored the fix-it
text in a blob of arbitrary size, but the size of the text was stored in
a separate 16 bit field. For really large fix-its, the size won't fit it
those 16 bits, and the compiler crashes.
Switch to a variable length encoding of the fit-it size. This is similar
to this issue:
https://github.com/llvm/llvm-project/commit/e26aea5b290165f3bccffab662a706d4a56f7540
We also remove a hard coded check in the clang library used to load .dia
files that failed for fix-its whose size doesn't fit in 16 bits.
---
.../Frontend/SerializedDiagnosticPrinter.cpp | 2 +-
.../test/Misc/serialized-diags-large-fixit.m | 45 +++++++++++++++++++
clang/tools/libclang/CXLoadedDiagnostic.cpp | 3 --
3 files changed, 46 insertions(+), 4 deletions(-)
create mode 100644 clang/test/Misc/serialized-diags-large-fixit.m
diff --git a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 58d080f5504c2..47585d43bb5e6 100644
--- a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -500,7 +500,7 @@ void SDiagsWriter::EmitBlockInfoBlock() {
Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
AddRangeLocationAbbrev(*Abbrev);
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Text size.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text.
Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
Abbrev));
diff --git a/clang/test/Misc/serialized-diags-large-fixit.m b/clang/test/Misc/serialized-diags-large-fixit.m
new file mode 100644
index 0000000000000..b2fb1fed07d00
--- /dev/null
+++ b/clang/test/Misc/serialized-diags-large-fixit.m
@@ -0,0 +1,45 @@
+// RUN: %clang -fsyntax-only -fobjc-runtime=macosx-10.8 \
+// RUN: -Wno-objc-root-class --serialize-diagnostics %t.dia %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=TEXT
+// RUN: c-index-test -read-diagnostics %t.dia 2>&1 \
+// RUN: | FileCheck %s --check-prefix=SERIALIZED
+
+// Form an identifier larger than 64 KiB without making the test file enormous.
+#define CAT_IMPL(A, B) A##B
+#define CAT(A, B) CAT_IMPL(A, B)
+#define A0 a
+#define A1 CAT(A0, A0)
+#define A2 CAT(A1, A1)
+#define A3 CAT(A2, A2)
+#define A4 CAT(A3, A3)
+#define A5 CAT(A4, A4)
+#define A6 CAT(A5, A5)
+#define A7 CAT(A6, A6)
+#define A8 CAT(A7, A7)
+#define A9 CAT(A8, A8)
+#define A10 CAT(A9, A9)
+#define A11 CAT(A10, A10)
+#define A12 CAT(A11, A11)
+#define A13 CAT(A12, A12)
+#define A14 CAT(A13, A13)
+#define A15 CAT(A14, A14)
+#define A16 CAT(A15, A15)
+#define LARGE_IDENTIFIER CAT(A16, z)
+
+ at protocol Protocol
+ at property int LARGE_IDENTIFIER;
+ at end
+
+ at interface MyClass <Protocol>
+ at end
+
+ at implementation MyClass
+ at end
+
+// TEXT: warning: auto property synthesis will not synthesize property
+// TEXT: note: add a '@synthesize' directive
+// SERIALIZED: warning: auto property synthesis will not synthesize property
+// SERIALIZED: note: add a '@synthesize' directive
+// SERIALIZED: FIXIT:
+// SERIALIZED-SAME: z;
+// SERIALIZED: Number of diagnostics: 1
diff --git a/clang/tools/libclang/CXLoadedDiagnostic.cpp b/clang/tools/libclang/CXLoadedDiagnostic.cpp
index ed89a6a7754da..bfb02d4dcf49d 100644
--- a/clang/tools/libclang/CXLoadedDiagnostic.cpp
+++ b/clang/tools/libclang/CXLoadedDiagnostic.cpp
@@ -366,9 +366,6 @@ DiagLoader::visitFixitRecord(const serialized_diags::Location &Start,
CXSourceRange SR;
if (std::error_code EC = readRange(Start, End, SR))
return EC;
- // FIXME: Why do we care about long strings?
- if (CodeToInsert.size() > 65536)
- return reportInvalidFile("Out-of-bounds string in FIXIT");
CurrentDiags.back()->FixIts.push_back(
std::make_pair(SR, TopDiags->copyString(CodeToInsert)));
return std::error_code();
More information about the cfe-commits
mailing list