handle_dynamic_symtab can attempt to read symbol and version data from
file offset 0 if the associated DT_ tags aren't found.

Fix this by only reading symbol and version data when non-zero file
offsets have been found.

https://sourceware.org/bugzilla/show_bug.cgi?id=32864

Suggested-by: Constantine Bytensky <cbyten...@gmail.com>
Signed-off-by: Aaron Merey <ame...@redhat.com>
---
 src/readelf.c | 50 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/readelf.c b/src/readelf.c
index 5b0e7b47..0452977f 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3047,18 +3047,25 @@ handle_dynamic_symtab (Ebl *ebl)
   Elf_Data *verdef_data = NULL;
   Elf_Data *verneed_data = NULL;
 
-  symdata = elf_getdata_rawchunk (
-      ebl->elf, offs[i_symtab],
-      gelf_fsize (ebl->elf, ELF_T_SYM, syments, EV_CURRENT), ELF_T_SYM);
-  symstrdata = elf_getdata_rawchunk (ebl->elf, offs[i_strtab], addrs[i_strsz],
-                                     ELF_T_BYTE);
-  versym_data = elf_getdata_rawchunk (
-      ebl->elf, offs[i_versym], syments * sizeof (Elf64_Half), ELF_T_HALF);
+  if (offs[i_symtab] != 0)
+    symdata = elf_getdata_rawchunk (
+       ebl->elf, offs[i_symtab],
+       gelf_fsize (ebl->elf, ELF_T_SYM, syments, EV_CURRENT), ELF_T_SYM);
+
+  if (offs[i_strtab] != 0)
+    symstrdata = elf_getdata_rawchunk (ebl->elf, offs[i_strtab], 
addrs[i_strsz],
+                                      ELF_T_BYTE);
+
+  if (offs[i_versym] != 0)
+    versym_data = elf_getdata_rawchunk (
+       ebl->elf, offs[i_versym], syments * sizeof (Elf64_Half), ELF_T_HALF);
 
   /* Get the verneed_data without vernaux.  */
-  verneed_data = elf_getdata_rawchunk (
-      ebl->elf, offs[i_verneed], addrs[i_verneednum] * sizeof (Elf64_Verneed),
-      ELF_T_VNEED);
+  if (offs[i_verneed] != 0)
+    verneed_data = elf_getdata_rawchunk (
+       ebl->elf, offs[i_verneed], addrs[i_verneednum] * sizeof (Elf64_Verneed),
+       ELF_T_VNEED);
+
   size_t vernauxnum = 0;
   size_t vn_next_offset = 0;
 
@@ -3071,14 +3078,18 @@ handle_dynamic_symtab (Ebl *ebl)
     }
 
   /* Update the verneed_data to include the vernaux.  */
-  verneed_data = elf_getdata_rawchunk (
-      ebl->elf, offs[i_verneed],
-      (addrs[i_verneednum] + vernauxnum) * sizeof (GElf_Verneed), ELF_T_VNEED);
+  if (offs[i_verneed] != 0)
+    verneed_data = elf_getdata_rawchunk (
+       ebl->elf, offs[i_verneed],
+       (addrs[i_verneednum] + vernauxnum) * sizeof (GElf_Verneed),
+       ELF_T_VNEED);
 
   /* Get the verdef_data without verdaux.  */
-  verdef_data = elf_getdata_rawchunk (
-      ebl->elf, offs[i_verdef], addrs[i_verdefnum] * sizeof (Elf64_Verdef),
-      ELF_T_VDEF);
+  if (offs[i_verdef] != 0)
+    verdef_data = elf_getdata_rawchunk (
+       ebl->elf, offs[i_verdef], addrs[i_verdefnum] * sizeof (Elf64_Verdef),
+       ELF_T_VDEF);
+
   size_t verdauxnum = 0;
   size_t vd_next_offset = 0;
 
@@ -3091,9 +3102,10 @@ handle_dynamic_symtab (Ebl *ebl)
     }
 
   /* Update the verdef_data to include the verdaux.  */
-  verdef_data = elf_getdata_rawchunk (
-      ebl->elf, offs[i_verdef],
-      (addrs[i_verdefnum] + verdauxnum) * sizeof (GElf_Verdef), ELF_T_VDEF);
+  if (offs[i_verdef] != 0)
+    verdef_data = elf_getdata_rawchunk (
+       ebl->elf, offs[i_verdef],
+       (addrs[i_verdefnum] + verdauxnum) * sizeof (GElf_Verdef), ELF_T_VDEF);
 
   unsigned int nsyms = (unsigned int)syments;
   process_symtab (ebl, nsyms, 0, 0, 0, symdata, versym_data, symstrdata,
-- 
2.49.0

Reply via email to