]> granicus.if.org Git - llvm/commitdiff
[llvm-readelf] - Report a warning when .hash section contains a chain with a cycle.
authorGeorge Rimar <grimar@accesssoftek.com>
Wed, 2 Oct 2019 14:11:35 +0000 (14:11 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Wed, 2 Oct 2019 14:11:35 +0000 (14:11 +0000)
It is possible to craft a .hash section that triggers an infinite loop
in llvm-readelf code. This patch fixes the issue and introduces
a warning.

Differential revision: https://reviews.llvm.org/D68086

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@373476 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-readobj/elf-hash-symbols.test
tools/llvm-readobj/ELFDumper.cpp

index b0140a2e9c1ceeeb7bfb26fecd15985b619a0cf1..4ffecf9fcc6d4bd4aab5e1560e434d355fa479fd 100644 (file)
@@ -361,3 +361,43 @@ ProgramHeaders:
     PAddr: 0x1000
     Sections:
       - Section: .dynamic
+
+## Show that we report a warning for a hash table which contains an entry of
+## the bucket array pointing to a cycle.
+
+# RUN: yaml2obj --docnum=6 %s -o %t6.so
+# RUN: llvm-readelf --hash-symbols %t6.so 2>&1 | FileCheck %s -DFILE=%t6.so --check-prefix=BROKEN
+
+# BROKEN:      Symbol table of .hash for image:
+# BROKEN-NEXT:  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name
+# BROKEN-NEXT:    1   0: 00000000     0 NOTYPE  LOCAL  DEFAULT UND aaa
+# BROKEN: warning: '[[FILE]]': .hash section is invalid: bucket 1: a cycle was detected in the linked chain
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_386
+Sections:
+  - Name:    .hash
+    Type:    SHT_HASH
+    Link:    .dynsym
+    Bucket:  [ 1 ]
+    Chain:   [ 1, 1 ]
+  - Name:  .dynamic
+    Type:  SHT_DYNAMIC
+    Entries:
+## llvm-readelf will read the hash table from the file offset
+## p_offset + (p_vaddr - DT_HASH) = p_offset + (0 - 0) = p_offset,
+## which is the start of PT_LOAD, i.e. the file offset of .hash.
+      - Tag:   DT_HASH
+        Value: 0x0
+DynamicSymbols:
+  - Name:    aaa
+  - Name:    bbb
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Sections:
+      - Section: .hash
+      - Section: .dynamic
index af3d0e967d10d26924ad807abc43fad0d686e536..1b3e8f4851df078f8017ee7f1ac507bc8b54ce3c 100644 (file)
@@ -3437,10 +3437,21 @@ template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
     for (uint32_t Buc = 0; Buc < SysVHash->nbucket; Buc++) {
       if (Buckets[Buc] == ELF::STN_UNDEF)
         continue;
+      std::vector<bool> Visited(SysVHash->nchain);
       for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash->nchain; Ch = Chains[Ch]) {
         if (Ch == ELF::STN_UNDEF)
           break;
+
+        if (Visited[Ch]) {
+          reportWarning(
+              createError(".hash section is invalid: bucket " + Twine(Ch) +
+                          ": a cycle was detected in the linked chain"),
+              this->FileName);
+          break;
+        }
+
         printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc);
+        Visited[Ch] = true;
       }
     }
   }