[lld] 7a20d6a - [ELF] Correctly compute .gdb_index size when symbol's name offset overflows
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 31 21:04:35 PDT 2022
Author: Fangrui Song
Date: 2022-08-31T21:04:26-07:00
New Revision: 7a20d6abe4e42ce5d19d50d7f90963440750507b
URL: https://github.com/llvm/llvm-project/commit/7a20d6abe4e42ce5d19d50d7f90963440750507b
DIFF: https://github.com/llvm/llvm-project/commit/7a20d6abe4e42ce5d19d50d7f90963440750507b.diff
LOG: [ELF] Correctly compute .gdb_index size when symbol's name offset overflows
if `nameOff` overflows, `size` may be underestimated.
In writeTo, `memcpy(buf + sym.nameOff, sym.name.data(), sym.name.size());` may
cause an out-of-bounds write, leading to a SIGSEGV.
Added:
Modified:
lld/ELF/SyntheticSections.cpp
lld/ELF/SyntheticSections.h
Removed:
################################################################################
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index abaae030b2a27..eb9272e41fd89 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2692,20 +2692,6 @@ size_t GdbIndexSection::computeSymtabSize() const {
return std::max<size_t>(NextPowerOf2(symbols.size() * 4 / 3), 1024);
}
-// Compute the output section size.
-void GdbIndexSection::initOutputSize() {
- size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8;
-
- for (GdbChunk &chunk : chunks)
- size += chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20;
-
- // Add the constant pool size if exists.
- if (!symbols.empty()) {
- GdbSymbol &sym = symbols.back();
- size += sym.nameOff + sym.name.size() + 1;
- }
-}
-
static SmallVector<GdbIndexSection::CuEntry, 0>
readCuList(DWARFContext &dwarf) {
SmallVector<GdbIndexSection::CuEntry, 0> ret;
@@ -2780,7 +2766,8 @@ readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
// Create a list of symbols from a given list of symbol names and types
// by uniquifying them by name.
-static SmallVector<GdbIndexSection::GdbSymbol, 0> createSymbols(
+static std::pair<SmallVector<GdbIndexSection::GdbSymbol, 0>, size_t>
+createSymbols(
ArrayRef<SmallVector<GdbIndexSection::NameAttrEntry, 0>> nameAttrs,
const SmallVector<GdbIndexSection::GdbChunk, 0> &chunks) {
using GdbSymbol = GdbIndexSection::GdbSymbol;
@@ -2858,7 +2845,7 @@ static SmallVector<GdbIndexSection::GdbSymbol, 0> createSymbols(
off += sym.name.size() + 1;
}
- return ret;
+ return {ret, off};
}
// Returns a newly-created .gdb_index section.
@@ -2908,8 +2895,14 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
auto *ret = make<GdbIndexSection>();
ret->chunks = std::move(chunks);
- ret->symbols = createSymbols(nameAttrs, ret->chunks);
- ret->initOutputSize();
+ std::tie(ret->symbols, ret->size) = createSymbols(nameAttrs, ret->chunks);
+
+ // Count the areas other than the constant pool.
+ ret->size += sizeof(GdbIndexHeader) + ret->computeSymtabSize() * 8;
+ for (GdbChunk &chunk : ret->chunks)
+ ret->size +=
+ chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20;
+
return ret;
}
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 8b29cbb9c3855..5f7321a803d70 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -787,7 +787,6 @@ class GdbIndexSection final : public SyntheticSection {
llvm::support::ulittle32_t constantPoolOff;
};
- void initOutputSize();
size_t computeSymtabSize() const;
// Each chunk contains information gathered from debug sections of a
More information about the llvm-commits
mailing list