[llvm] [DebugInfo][DWARF] Bounds-check the unit-index parallel table (PR #213285)

Matt Davis via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 3 06:38:26 PDT 2026


https://github.com/enferex updated https://github.com/llvm/llvm-project/pull/213285

>From 4ac0b3fde9af49c1b88cfc90151db3f35760828b Mon Sep 17 00:00:00 2001
From: Matt Davis <mattd at nvidia.com>
Date: Thu, 30 Jul 2026 19:50:54 +0000
Subject: [PATCH 1/3] [DebugInfo][DWARF] Bounds-check the unit-index parallel
 table

DWARFUnitIndex::parseImpl() sizes the Contribs array to Header.NumUnits, then
for each hash-table row reads a 32-bit Index from the .debug_{cu,tu}_index
section and writes Contribs[Index - 1]. Index == 0 is skipped, but there was no
upper bound, so a crafted index with Index > NumUnits writes a heap pointer one
or more slots past the array. Reject Index > NumUnits before the write.

Reachable from any consumer of a DWP package (llvm-dwarfdump, llvm-dwp, lldb,
llvm-symbolizer).

Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
---
 llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
index 08abcf13d0618..f5d7b1e19dd11 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
@@ -159,6 +159,8 @@ bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
     auto Index = IndexData.getU32(&Offset);
     if (!Index)
       continue;
+    if (Index > Header.NumUnits)
+      return false;
     Rows[i].Index = this;
     Rows[i].Contributions =
         std::make_unique<Entry::SectionContribution[]>(Header.NumColumns);

>From da5c6ac566803ec1b35141ec821bb5e188e8ff13 Mon Sep 17 00:00:00 2001
From: Matt Davis <mattd at nvidia.com>
Date: Thu, 30 Jul 2026 19:50:55 +0000
Subject: [PATCH 2/3] [DebugInfo][DWARF] Add unit test for unit-index
 parallel-table bounds check

Feed a crafted .debug_cu_index whose parallel-table row index exceeds NumUnits
and check that DWARFUnitIndex::parse() returns false instead of writing a heap
pointer out of bounds.

Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>
---
 llvm/unittests/DebugInfo/DWARF/CMakeLists.txt |  1 +
 .../DebugInfo/DWARF/DWARFUnitIndexTest.cpp    | 63 +++++++++++++++++++
 2 files changed, 64 insertions(+)
 create mode 100644 llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp

diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
index 167f1b310cbc6..98c4e750176cc 100644
--- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
@@ -28,6 +28,7 @@ add_llvm_unittest(DebugInfoDWARFTests
   DWARFExpressionCompactPrinterTest.cpp
   DWARFFormValueTest.cpp
   DWARFListTableTest.cpp
+  DWARFUnitIndexTest.cpp
   DWARFLocationExpressionTest.cpp
   DWARFVerifierTest.cpp
   )
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp
new file mode 100644
index 0000000000000..b11f508dd8328
--- /dev/null
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp
@@ -0,0 +1,63 @@
+//===- llvm/unittest/DebugInfo/DWARF/DWARFUnitIndexTest.cpp ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Endian.h"
+#include "gtest/gtest.h"
+#include <cstdint>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+static void appendU32(std::vector<uint8_t> &B, uint32_t V) {
+  uint8_t Tmp[4];
+  support::endian::write32le(Tmp, V);
+  B.insert(B.end(), Tmp, Tmp + 4);
+}
+
+static void appendU64(std::vector<uint8_t> &B, uint64_t V) {
+  uint8_t Tmp[8];
+  support::endian::write64le(Tmp, V);
+  B.insert(B.end(), Tmp, Tmp + 8);
+}
+
+// A crafted .debug_cu_index (version 2) with one hash bucket whose parallel-
+// table Index is NumUnits + 1. Without the bounds check parseImpl() writes
+// Contribs[Index - 1], one slot past a heap array sized to NumUnits. parse()
+// must reject it and leave the index empty.
+TEST(DWARFUnitIndexTest, RejectsRowIndexBeyondNumUnits) {
+  std::vector<uint8_t> Buffer;
+  // Header: Version=2, NumColumns=1, NumUnits=1, NumBuckets=1.
+  appendU32(Buffer, 2);
+  appendU32(Buffer, 1);
+  appendU32(Buffer, 1);
+  appendU32(Buffer, 1);
+  // Hash table of signatures: NumBuckets x u64.
+  appendU64(Buffer, 0xdeadbeefULL);
+  // Parallel table of indexes: NumBuckets x u32. Index = NumUnits + 1 = 2.
+  appendU32(Buffer, 2);
+  // Column headers: NumColumns x u32 (DW_SECT_INFO serializes to 1 under v2).
+  appendU32(Buffer, 1);
+  // Table of section offsets: NumUnits*NumColumns x u32.
+  appendU32(Buffer, 0);
+  // Table of section sizes: NumUnits*NumColumns x u32.
+  appendU32(Buffer, 0);
+
+  DataExtractor Data(
+      StringRef(reinterpret_cast<const char *>(Buffer.data()), Buffer.size()),
+      /*IsLittleEndian=*/true);
+  DWARFUnitIndex Index(DW_SECT_INFO);
+  EXPECT_FALSE(Index.parse(Data));
+  // On failure parse() resets the header, so the index is falsy.
+  EXPECT_FALSE(static_cast<bool>(Index));
+}
+
+} // end anonymous namespace

>From 56dd8effb12a2bee79191ff036e96180c0602820 Mon Sep 17 00:00:00 2001
From: Matt Davis <mattd at nvidia.com>
Date: Mon, 3 Aug 2026 13:32:08 +0000
Subject: [PATCH 3/3] Remove file path from header comment.

---
 llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp
index b11f508dd8328..fa8c8227ea4c4 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFUnitIndexTest.cpp
@@ -1,4 +1,4 @@
-//===- llvm/unittest/DebugInfo/DWARF/DWARFUnitIndexTest.cpp ---------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.



More information about the llvm-commits mailing list