[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