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

David Spickett via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 3 07:04:54 PDT 2026


================
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
----------------
DavidSpickett wrote:

We try to avoid anonymous namespace when we can and I don't think you need one for a unit test file.

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


More information about the llvm-commits mailing list