[llvm] [llvm-objdump][ELF]Fix crash when reading strings from .dynstr(#86612) (PR #125679)

Ruoyu Qiu via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 10 04:16:22 PST 2025


https://github.com/cabbaken updated https://github.com/llvm/llvm-project/pull/125679

>From 2cc575140bce6a42b48d265287827cdf64afd284 Mon Sep 17 00:00:00 2001
From: cabbaken <cabbaken at outlook.com>
Date: Sun, 26 Jan 2025 17:37:46 +0800
Subject: [PATCH 1/3] [llvm-objdump][ELF]Fix crash when reading strings from
 .dynstr(#86612)

This change introduces a check for the strtab offset
to prevent llvm-objdump from crashing when processing
malformed ELF files.
Additionally, it modifies how llvm-objdump handles and
outputs malformed ELF files with invalid string offsets.
More info: https://discourse.llvm.org/t/should-llvm-objdump-objdump-display-actual-corrupted-values-in-malformed-elf-files/84391

Signed-off-by: cabbaken <cabbaken at outlook.com>
---
 .../llvm-objdump/ELF/dynamic-section.test     | 34 +++++++++++++++++++
 llvm/tools/llvm-objdump/ELFDump.cpp           | 23 +++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
index 5205c5a3876d5fb..33ca7e5b40c2628 100644
--- a/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
+++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
@@ -438,6 +438,9 @@ ProgramHeaders:
 # RUN: yaml2obj --docnum=4 %s -o %t4
 # RUN: llvm-objdump -p %t4 | FileCheck %s --strict-whitespace --check-prefix=INDENT
 
+# RUN: yaml2obj --docnum=5 %s -o %t5
+# RUN: llvm-objdump -p %t5 | FileCheck %s --strict-whitespace --check-prefix=INDENT
+
 # INDENT: {{^}}Dynamic Section:
 # INDENT: {{^}}  NEEDED 0x
 
@@ -470,3 +473,34 @@ Sections:
        Value: 0x1
      - Tag:   DT_NULL
        Value: 0x0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:    .dynstr
+    Type:    SHT_STRTAB
+    Address: 0x1000
+    Size:    0x10
+    Content: "004400550066007700"
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+    Entries:
+     - Tag:   DT_NEEDED
+       Value: 0x1245657656
+     - Tag:   DT_STRTAB
+       Value: 0x1000
+     - Tag:   DT_NULL
+       Value: 0x0
+ProgramHeaders:
+  - Type:     PT_LOAD
+    VAddr:    0x1000
+    FirstSec: .dynstr
+    LastSec:  .dynamic
+  - Type:     PT_DYNAMIC
+    VAddr:    0x101D
+    FirstSec: .dynamic
+    LastSec:  .dynamic
\ No newline at end of file
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp
index e9e5b059f1786e2..9aa54fc58d67fe3 100644
--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -14,8 +14,11 @@
 #include "ELFDump.h"
 
 #include "llvm-objdump.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Demangle/Demangle.h"
+#include "llvm/Object/ELF.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/ELFTypes.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -221,6 +224,20 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicSection() {
   std::string TagFmt = "  %-" + std::to_string(MaxLen) + "s ";
 
   outs() << "\nDynamic Section:\n";
+  auto StringTableSize = (typename ELFT::Xword)0;
+  for (const auto &Sec : cantFail(Elf.sections())) {
+    if (Sec.sh_type == ELF::SHT_STRTAB)
+      StringTableSize =
+          StringTableSize < Sec.sh_size ? Sec.sh_size : StringTableSize;
+  }
+  for (const typename ELFT::Dyn &Dyn : DynamicEntries) {
+    if (Dyn.d_tag == ELF::DT_STRSZ) {
+      StringTableSize =
+          StringTableSize < Dyn.getVal() ? Dyn.getVal() : StringTableSize;
+      break;
+    }
+  }
+
   for (const typename ELFT::Dyn &Dyn : DynamicEntries) {
     if (Dyn.d_tag == ELF::DT_NULL)
       continue;
@@ -235,6 +252,12 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicSection() {
       Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf);
       if (StrTabOrErr) {
         const char *Data = StrTabOrErr->data();
+        if (Dyn.getVal() >= StringTableSize) {
+          reportWarning("invalid string table offset", Obj.getFileName());
+          outs() << format(TagFmt.c_str(), Str.c_str())
+                 << format(Fmt, (uint64_t)Dyn.getVal());
+          continue;
+        }
         outs() << format(TagFmt.c_str(), Str.c_str()) << Data + Dyn.getVal()
                << "\n";
         continue;

>From e8414fc23ffdc1cecbc702302b7a35f2a1892b81 Mon Sep 17 00:00:00 2001
From: cabbaken <cabbaken at outlook.com>
Date: Thu, 6 Feb 2025 16:46:24 +0800
Subject: [PATCH 2/3] [llvm-objdump][ELF] Fix test file format

Signed-off-by: Ruoyu Qiu <cabbaken at outlook.com>
---
 .../llvm-objdump/ELF/dynamic-section.test      | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
index 33ca7e5b40c2628..39c1a241a8667e5 100644
--- a/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
+++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
@@ -438,9 +438,6 @@ ProgramHeaders:
 # RUN: yaml2obj --docnum=4 %s -o %t4
 # RUN: llvm-objdump -p %t4 | FileCheck %s --strict-whitespace --check-prefix=INDENT
 
-# RUN: yaml2obj --docnum=5 %s -o %t5
-# RUN: llvm-objdump -p %t5 | FileCheck %s --strict-whitespace --check-prefix=INDENT
-
 # INDENT: {{^}}Dynamic Section:
 # INDENT: {{^}}  NEEDED 0x
 
@@ -474,6 +471,19 @@ Sections:
      - Tag:   DT_NULL
        Value: 0x0
 
+# RUN: yaml2obj --docnum=5 %s -o %t5
+# RUN: llvm-objdump -p %t5 2>&1 | FileCheck %s --strict-whitespace -DFILE=%t5 --check-prefix=WARN
+
+# WARN: Program Header:
+# WARN:     LOAD off    0x00000000000000b0 vaddr 0x0000000000001000 paddr 0x0000000000001000 align 2**0
+# WARN:          filesz 0x0000000000000040 memsz 0x0000000000000040 flags ---
+# WARN:  DYNAMIC off    0x00000000000000c0 vaddr 0x000000000000101d paddr 0x000000000000101d align 2**0
+# WARN:          filesz 0x0000000000000030 memsz 0x0000000000000030 flags ---
+# WARN: Dynamic Section:
+# WARN: : warning: '[[FILE]]': invalid string table offset
+# WARN:  NEEDED 0x0000001245657656
+# WARN:  STRTAB 0x0000000000001000
+
 --- !ELF
 FileHeader:
   Class:   ELFCLASS64
@@ -503,4 +513,4 @@ ProgramHeaders:
   - Type:     PT_DYNAMIC
     VAddr:    0x101D
     FirstSec: .dynamic
-    LastSec:  .dynamic
\ No newline at end of file
+    LastSec:  .dynamic

>From 1acfb611b68a0d73be45902dbc9917170ab7174b Mon Sep 17 00:00:00 2001
From: Ruoyu Qiu <cabbaken at outlook.com>
Date: Mon, 10 Feb 2025 20:16:13 +0800
Subject: [PATCH 3/3] Update
 llvm/test/tools/llvm-objdump/ELF/dynamic-section.test

Co-authored-by: James Henderson <James.Henderson at sony.com>
---
 llvm/test/tools/llvm-objdump/ELF/dynamic-section.test | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
index 39c1a241a8667e5..72642f64ceb9d8d 100644
--- a/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
+++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
@@ -480,7 +480,7 @@ Sections:
 # WARN:  DYNAMIC off    0x00000000000000c0 vaddr 0x000000000000101d paddr 0x000000000000101d align 2**0
 # WARN:          filesz 0x0000000000000030 memsz 0x0000000000000030 flags ---
 # WARN: Dynamic Section:
-# WARN: : warning: '[[FILE]]': invalid string table offset
+# WARN: warning: '[[FILE]]': invalid string table offset
 # WARN:  NEEDED 0x0000001245657656
 # WARN:  STRTAB 0x0000000000001000
 



More information about the llvm-commits mailing list