[llvm] e19628f - [llvm-readobj] - Fix crashes and misbehaviors when reading strings from broken string tables.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 20 04:23:36 PDT 2020


Author: Georgii Rymar
Date: 2020-04-20T14:14:17+03:00
New Revision: e19628fde58e2909b5fcd051c231cf1d62f05833

URL: https://github.com/llvm/llvm-project/commit/e19628fde58e2909b5fcd051c231cf1d62f05833
DIFF: https://github.com/llvm/llvm-project/commit/e19628fde58e2909b5fcd051c231cf1d62f05833.diff

LOG: [llvm-readobj] - Fix crashes and misbehaviors when reading strings from broken string tables.

There are cases when we either might print garbage or crash when
reading strings for dumping dynamic tags.

For example when a string table is not null-terminated or goes past the EOF.
This patch fixes issues mentioned.

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

Added: 
    

Modified: 
    llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
    llvm/test/tools/llvm-readobj/ELF/loadname.test
    llvm/test/tools/llvm-readobj/ELF/needed-libs.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
index 7b941bfd685d..ed72118c4ffc 100644
--- a/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
+++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
@@ -3,9 +3,9 @@
 
 # RUN: yaml2obj %s --docnum=1 -o %t.bad-size
 # RUN: llvm-readobj --all %t.bad-size 2>&1 \
-# RUN:   | FileCheck %s -DFILE=%t.bad-size --implicit-check-not=warning --check-prefix WARN
+# RUN:   | FileCheck %s -DFILE=%t.bad-size --implicit-check-not=warning: --check-prefix WARN
 # RUN: llvm-readelf --all %t.bad-size 2>&1 \
-# RUN:   | FileCheck %s -DFILE=%t.bad-size --implicit-check-not=warning --check-prefix WARN-GNU
+# RUN:   | FileCheck %s -DFILE=%t.bad-size --implicit-check-not=warning: --check-prefix WARN-GNU
 
 # WARN: warning: '[[FILE]]': invalid PT_DYNAMIC size (0x4){{$}}
 # WARN: warning: '[[FILE]]': section with index 1 has invalid size (0x4){{$}}
@@ -95,47 +95,47 @@ ProgramHeaders:
 # RUN: llvm-readelf --dynamic-table %t.bad-string 2>&1 | \
 # RUN:   FileCheck %s --implicit-check-not=warning: --check-prefix BAD-STRING-GNU -DFILE=%t.bad-string
 
-# BAD-STRING-LLVM:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6: it goes past the end of the table (0xb1)
 # BAD-STRING-LLVM:      LoadName: <?>
 # BAD-STRING-LLVM:      DynamicSection [ (10 entries)
 # BAD-STRING-LLVM-NEXT:   Tag                Type      Name/Value
 # BAD-STRING-LLVM-NEXT:   0x0000000000000005 STRTAB    0x1000
 # BAD-STRING-LLVM-NEXT:   0x000000000000000A STRSZ     1 (bytes)
-# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2: it goes past the end of the table (0xb1)
 # BAD-STRING-LLVM-NEXT:   0x0000000000000001 NEEDED    Shared library: [<?>]
-# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3: it goes past the end of the table (0xb1)
 # BAD-STRING-LLVM-NEXT:   0x000000007FFFFFFF FILTER    Filter library: [<?>]
-# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4: it goes past the end of the table (0xb1)
 # BAD-STRING-LLVM-NEXT:   0x000000007FFFFFFD AUXILIARY Auxiliary library: [<?>]
-# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5: it goes past the end of the table (0xb1)
 # BAD-STRING-LLVM-NEXT:   0x000000007FFFFFFE USED      Not needed object: [<?>]
 ## Note: there is no "string table at offset 0xb0..." warning here, because it was printed earlier.
 # BAD-STRING-LLVM-NEXT:   0x000000000000000E SONAME    Library soname: [<?>]
-# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7: it goes past the end of the table (0xb1)
 # BAD-STRING-LLVM-NEXT:   0x000000000000000F RPATH     Library rpath: [<?>]
-# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8: it goes past the end of the table (0xb1)
 # BAD-STRING-LLVM-NEXT:   0x000000000000001D RUNPATH   Library runpath: [<?>]
 # BAD-STRING-LLVM-NEXT:   0x0000000000000000 NULL      0x0
 # BAD-STRING-LLVM-NEXT: ]
 
-# BAD-STRING-GNU:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6: it goes past the end of the table (0xb1)
 # BAD-STRING-GNU-NEXT: Dynamic section at offset 0xb1 contains 10 entries:
 # BAD-STRING-GNU-NEXT:   Tag                Type        Name/Value
 # BAD-STRING-GNU-NEXT:   0x0000000000000005 (STRTAB)    0x1000
 # BAD-STRING-GNU-NEXT:   0x000000000000000a (STRSZ)     1 (bytes)
-# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2: it goes past the end of the table (0xb1)
 # BAD-STRING-GNU-NEXT:   0x0000000000000001 (NEEDED)    Shared library: [<?>]
-# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3: it goes past the end of the table (0xb1)
 # BAD-STRING-GNU-NEXT:   0x000000007fffffff (FILTER)    Filter library: [<?>]
-# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4: it goes past the end of the table (0xb1)
 # BAD-STRING-GNU-NEXT:   0x000000007ffffffd (AUXILIARY) Auxiliary library: [<?>]
-# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5: it goes past the end of the table (0xb1)
 # BAD-STRING-GNU-NEXT:   0x000000007ffffffe (USED)      Not needed object: [<?>]
 ## Note: there is no "string table at offset 0xb6..." warning here, because it was printed earlier.
 # BAD-STRING-GNU-NEXT:   0x000000000000000e (SONAME)    Library soname: [<?>]
-# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7: it goes past the end of the table (0xb1)
 # BAD-STRING-GNU-NEXT:   0x000000000000000f (RPATH)     Library rpath: [<?>]
-# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8: it goes past the end of the table (0xb1)
 # BAD-STRING-GNU-NEXT:   0x000000000000001d (RUNPATH)   Library runpath: [<?>]
 # BAD-STRING-GNU-NEXT:   0x0000000000000000 (NULL)      0x0
 
@@ -279,3 +279,133 @@ ProgramHeaders:
     VAddr: 0x1000
     Sections:
       - Section: .dynamic
+
+## Check how we handle cases when the dynamic string table is not null-terminated.
+
+## Case A: the value of the DT_STRSZ tag is equal to the size of
+##         the not null-terminated dynamic string table.
+# RUN: yaml2obj %s -DSTRSZ=7 --docnum=6 -o %t6
+# RUN: llvm-readobj --dynamic-table %t6 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t6 --implicit-check-not=warning: --check-prefixes=NOT-TERMINATED,NOT-TERMINATED-GREQ
+# RUN: llvm-readelf --dynamic-table %t6 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t6 --implicit-check-not=warning: --check-prefixes=NOT-TERMINATED,NOT-TERMINATED-GREQ
+
+## Case B: the value of the DT_STRSZ tag is less than the size of
+##         the not null-terminated dynamic string table.
+# RUN: yaml2obj %s -DSTRSZ=6 --docnum=6 -o %t7
+# RUN: llvm-readobj --dynamic-table %t7 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t7 --implicit-check-not=warning: --check-prefixes=NOT-TERMINATED,NOT-TERMINATED-LESS
+# RUN: llvm-readelf --dynamic-table %t7 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t7 --implicit-check-not=warning: --check-prefixes=NOT-TERMINATED,NOT-TERMINATED-LESS
+
+## Case C: the value of the DT_STRSZ tag is one byte larger than the size of
+##         the not null-terminated dynamic string table.
+# RUN: yaml2obj %s -DSTRSZ=8 --docnum=6 -o %t8
+# RUN: llvm-readobj --dynamic-table %t8 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t8 --implicit-check-not=warning: --check-prefixes=NOT-TERMINATED,NOT-TERMINATED-GREQ
+# RUN: llvm-readelf --dynamic-table %t8 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t8 --implicit-check-not=warning: --check-prefixes=NOT-TERMINATED,NOT-TERMINATED-GREQ
+
+# NOT-TERMINATED:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4: the string table is not null-terminated
+# NOT-TERMINATED:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb0: the string table is not null-terminated
+# NOT-TERMINATED-NEXT: {{[(]?}}NEEDED{{[)]?}}    Shared library: [<?>]
+# NOT-TERMINATED-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb1: the string table is not null-terminated
+# NOT-TERMINATED-NEXT: {{[(]?}}FILTER{{[)]?}}    Filter library: [<?>]
+# NOT-TERMINATED-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2: the string table is not null-terminated
+# NOT-TERMINATED-NEXT: {{[(]?}}AUXILIARY{{[)]?}} Auxiliary library: [<?>]
+# NOT-TERMINATED-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3: the string table is not null-terminated
+# NOT-TERMINATED-NEXT: {{[(]?}}USED{{[)]?}}      Not needed object: [<?>]
+# NOT-TERMINATED-NEXT: {{[(]?}}SONAME{{[)]?}}    Library soname: [<?>]
+# NOT-TERMINATED-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5: the string table is not null-terminated
+# NOT-TERMINATED-NEXT: {{[(]?}}RPATH{{[)]?}}     Library rpath: [<?>]
+# NOT-TERMINATED-GREQ-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6: the string table is not null-terminated
+# NOT-TERMINATED-LESS-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6: it goes past the end of the table (0xb6)
+# NOT-TERMINATED-NEXT: {{[(]?}}RUNPATH{{[)]?}}   Library runpath: [<?>]
+# NOT-TERMINATED-NEXT: {{[(]?}}NULL{{[)]?}}      0x0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:    .dynstr
+    Type:    SHT_STRTAB
+    Address: 0x1000
+    Content: '746573742e736f' ## "test.so", not null terminated.
+  - Type:    Fill
+    Pattern: "61626300" ## 'a', 'b', 'c', '\0'.
+    Size:    "4"
+  - Name:    .dynamic
+    Type:    SHT_DYNAMIC
+    Address: 0x1100
+    Entries:
+      - Tag:   DT_STRTAB
+        Value: 0x1000
+      - Tag:   DT_STRSZ
+        Value: [[STRSZ]]
+      - Tag:   DT_NEEDED
+        Value: 0
+      - Tag:   DT_FILTER
+        Value: 1
+      - Tag:   DT_AUXILIARY
+        Value: 2
+      - Tag:   DT_USED
+        Value: 3
+      - Tag:   DT_SONAME
+        Value: 4
+      - Tag:   DT_RPATH
+        Value: 5
+      - Tag:   DT_RUNPATH
+        Value: 6
+      - Tag:   DT_NULL
+        Value: 0
+ProgramHeaders:
+  - Type: PT_LOAD
+    VAddr: 0x1000
+    Sections:
+      - Section: .dynstr
+      - Section: .dynamic
+  - Type: PT_DYNAMIC
+    VAddr: 0x1100
+    Sections:
+      - Section: .dynamic
+
+## Check that we emit an appropriate warning when the dynamic string table ends past the end of the file.
+
+## Case A: the value of DT_STRSZ tag is set so that the string table ends
+## right before the EOF. No warning should be emitted.
+# RUN: yaml2obj %s -DSTRSZ=0x210 --docnum=6 -o %t9.1
+# RUN: llvm-readobj --dynamic-table %t9.1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --check-prefix=BEFORE-THE-EOF
+# RUN: llvm-readelf --dynamic-table %t9.1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --check-prefix=BEFORE-THE-EOF
+
+## Note: The code reads the data in [DT_STRTAB, DT_STRTAB + DT_STRSZ] as the string table
+## as normal. Since the file ends with a zero byte, strings are dumped, but if it didn't,
+## we'd get <?> printed instead. The important bit is that we don't get the past the end warning.
+
+# BEFORE-THE-EOF:      {{[(]?}}NEEDED{{[)]?}}    Shared library: [test.soabc]
+# BEFORE-THE-EOF-NEXT: {{[(]?}}FILTER{{[)]?}}    Filter library: [est.soabc]
+# BEFORE-THE-EOF-NEXT: {{[(]?}}AUXILIARY{{[)]?}} Auxiliary library: [st.soabc]
+# BEFORE-THE-EOF-NEXT: {{[(]?}}USED{{[)]?}}      Not needed object: [t.soabc]
+# BEFORE-THE-EOF-NEXT: {{[(]?}}SONAME{{[)]?}}    Library soname: [.soabc]
+# BEFORE-THE-EOF-NEXT: {{[(]?}}RPATH{{[)]?}}     Library rpath: [soabc]
+# BEFORE-THE-EOF-NEXT: {{[(]?}}RUNPATH{{[)]?}}   Library runpath: [oabc]
+# BEFORE-THE-EOF-NEXT: {{[(]?}}NULL{{[)]?}}      0x0
+
+## Case B: the value of DT_STRSZ tag is set so that the string table goes 1 byte past the EOF.
+# RUN: yaml2obj %s -DSTRSZ=0x211 --docnum=6 -o %t9.2
+# RUN: llvm-readobj --dynamic-table %t9.2 2>&1 | FileCheck %s -DFILE=%t9.2 --check-prefix=PAST-THE-EOF
+# RUN: llvm-readelf --dynamic-table %t9.2 2>&1 | FileCheck %s -DFILE=%t9.2 --check-prefix=PAST-THE-EOF
+
+# PAST-THE-EOF:      warning: '[[FILE]]': string table at offset 0xb0 with size 0x211 goes past the end of the file (0x2c0)
+# PAST-THE-EOF:      {{[(]?}}NEEDED{{[)]?}}    Shared library: [<?>]
+# PAST-THE-EOF-NEXT: {{[(]?}}FILTER{{[)]?}}    Filter library: [<?>]
+# PAST-THE-EOF-NEXT: {{[(]?}}AUXILIARY{{[)]?}} Auxiliary library: [<?>]
+# PAST-THE-EOF-NEXT: {{[(]?}}USED{{[)]?}}      Not needed object: [<?>]
+# PAST-THE-EOF-NEXT: {{[(]?}}SONAME{{[)]?}}    Library soname: [<?>]
+# PAST-THE-EOF-NEXT: {{[(]?}}RPATH{{[)]?}}     Library rpath: [<?>]
+# PAST-THE-EOF-NEXT: {{[(]?}}RUNPATH{{[)]?}}   Library runpath: [<?>]
+# PAST-THE-EOF-NEXT: {{[(]?}}NULL{{[)]?}}      0x0

diff  --git a/llvm/test/tools/llvm-readobj/ELF/loadname.test b/llvm/test/tools/llvm-readobj/ELF/loadname.test
index aba3a5ba2af1..5fda41107284 100644
--- a/llvm/test/tools/llvm-readobj/ELF/loadname.test
+++ b/llvm/test/tools/llvm-readobj/ELF/loadname.test
@@ -14,7 +14,7 @@
 # GNU:       Dynamic section at offset 0x80 contains 4 entries:
 # GNU-NEXT:   Tag                Type     Name/Value
 # GNU-NEXT:   0x0000000000000005 (STRTAB) 0x0
-# GNU-NEXT:   0x000000000000000a (STRSZ)  7 (bytes)
+# GNU-NEXT:   0x000000000000000a (STRSZ)  8 (bytes)
 # GNU-NEXT:   0x000000000000000e (SONAME) Library soname: [test.so]
 # GNU-NEXT:   0x0000000000000000 (NULL)   0x0
 
@@ -37,7 +37,7 @@ Sections:
       - Tag:   DT_STRTAB
         Value: [[DTSTRTABVAL]]
       - Tag:   DT_STRSZ
-        Value: 0x0000000000000007
+        Value: 0x0000000000000008
       - Tag:   DT_SONAME
         Value: 0x0000000000000000
       - Tag:   DT_NULL

diff  --git a/llvm/test/tools/llvm-readobj/ELF/needed-libs.test b/llvm/test/tools/llvm-readobj/ELF/needed-libs.test
index 536a54b51117..1c5f4978f093 100644
--- a/llvm/test/tools/llvm-readobj/ELF/needed-libs.test
+++ b/llvm/test/tools/llvm-readobj/ELF/needed-libs.test
@@ -10,8 +10,8 @@
 ## Document that we also sort error entries.
 
 #      NEEDED-LIBS:{{^}}NeededLibraries [{{$}}
-# NEEDED-LIBS-NEXT:  warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x9999a11, it goes past the end of the table (0x85){{$}}
-# NEEDED-LIBS-NEXT:  warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x1111189, it goes past the end of the table (0x85){{$}}
+# NEEDED-LIBS-NEXT:  warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x9999a11: it goes past the end of the table (0x85){{$}}
+# NEEDED-LIBS-NEXT:  warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x1111189: it goes past the end of the table (0x85){{$}}
 # NEEDED-LIBS-NEXT:{{^}}  <?>{{$}}
 # NEEDED-LIBS-NEXT:{{^}}  <?>{{$}}
 # NEEDED-LIBS-NEXT:{{^}}  aaa{{$}}
@@ -63,11 +63,11 @@ ProgramHeaders:
 # RUN: llvm-readelf --needed-libs %t2 2>&1 | \
 # RUN:   FileCheck %s -DFILE=%t2 --implicit-check-not=warning: --check-prefix=EMPTY-DYNSTR
 
-# EMPTY-DYNSTR:      warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x78, it goes past the end of the table (0x78)
+# EMPTY-DYNSTR:      warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x78: it goes past the end of the table (0x78)
 # EMPTY-DYNSTR-LLVM: LoadName: <?>
 # EMPTY-DYNSTR:      NeededLibraries [
-# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x79, it goes past the end of the table (0x78)
-# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x7a, it goes past the end of the table (0x78)
+# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x79: it goes past the end of the table (0x78)
+# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x7a: it goes past the end of the table (0x78)
 # EMPTY-DYNSTR-NEXT:   <?>
 # EMPTY-DYNSTR-NEXT:   <?>
 # EMPTY-DYNSTR-NEXT: ]

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index fcbfbbb351db..9930c03c6d97 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -2558,24 +2558,41 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
 
 template <class ELFT>
 StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
-  auto WarnAndReturn = [this](const Twine &Msg) {
-    reportUniqueWarning(createError(Msg));
+  if (DynamicStringTable.empty() && !DynamicStringTable.data()) {
+    reportUniqueWarning(createError("string table was not found"));
     return "<?>";
-  };
-
-  if (DynamicStringTable.empty() && !DynamicStringTable.data())
-    return WarnAndReturn("string table was not found");
+  }
 
-  if (Value < DynamicStringTable.size())
-    return DynamicStringTable.data() + Value;
+  auto WarnAndReturn = [this](const Twine &Msg, uint64_t Offset) {
+    reportUniqueWarning(createError("string table at offset 0x" +
+                                    Twine::utohexstr(Offset) + Msg));
+    return "<?>";
+  };
 
+  const uint64_t FileSize = ObjF->getELFFile()->getBufSize();
   const uint64_t Offset =
       (const uint8_t *)DynamicStringTable.data() - ObjF->getELFFile()->base();
-  return WarnAndReturn(
-      "string table at offset 0x" + Twine::utohexstr(Offset) +
-      ": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) +
-      ", it goes past the end of the table (0x" +
-      Twine::utohexstr(Offset + DynamicStringTable.size()) + ")");
+  if (DynamicStringTable.size() > FileSize - Offset)
+    return WarnAndReturn(" with size 0x" +
+                             Twine::utohexstr(DynamicStringTable.size()) +
+                             " goes past the end of the file (0x" +
+                             Twine::utohexstr(FileSize) + ")",
+                         Offset);
+
+  if (Value >= DynamicStringTable.size())
+    return WarnAndReturn(
+        ": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) +
+            ": it goes past the end of the table (0x" +
+            Twine::utohexstr(Offset + DynamicStringTable.size()) + ")",
+        Offset);
+
+  if (DynamicStringTable.back() != '\0')
+    return WarnAndReturn(": unable to read the string at 0x" +
+                             Twine::utohexstr(Offset + Value) +
+                             ": the string table is not null-terminated",
+                         Offset);
+
+  return DynamicStringTable.data() + Value;
 }
 
 template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {


        


More information about the llvm-commits mailing list