Fix: nm: SEGV on unknow address at nm.c:718 in print_symname
authorNick Clifton <nickc@redhat.com>
Thu, 28 Sep 2023 11:37:59 +0000 (12:37 +0100)
committerNick Clifton <nickc@redhat.com>
Thu, 28 Sep 2023 11:37:59 +0000 (12:37 +0100)
  PR 30886 * elf-bfd.h (struct elf_obj_tdata): Add dt_strsz field.
  * elf.c (_bfd_elf_get_dynamic_symbols): Add a NUL byte at the end of the string table. Initialise the dt_strsz field. (_bfd_elf_slurp_version_tables): Only free the contents if they were malloc'ed. Add checks before setting string pointers in the dt_strtab buffer.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c

index 2eee20fae0cd582c53a40a22529124137be2abf8..ed9db240eb5e20d26bdcefc2d3a67ce267bd040c 100644 (file)
@@ -1,3 +1,14 @@
+2023-09-28  Nick Clifton  <nickc@redhat.com>
+
+       PR 30886
+       * elf-bfd.h (struct elf_obj_tdata): Add dt_strsz field.
+       * elf.c (_bfd_elf_get_dynamic_symbols): Add a NUL byte at the end
+       of the string table.
+       Initialise the dt_strsz field.
+       (_bfd_elf_slurp_version_tables): Only free the contents if they
+       were malloc'ed.
+       Add checks before setting string pointers in the dt_strtab buffer.
+
 2023-09-27  Nick Clifton  <nickc@redhat.com>
 
        PR 30885
index 52d4d39b7050e6cc4ee3d30109267621b3bc8572..335081ec6296310d1894aa4a807c981d4a75e8c8 100644 (file)
@@ -2039,7 +2039,8 @@ struct elf_obj_tdata
   size_t dt_symtab_count;
   size_t dt_verdef_count;
   size_t dt_verneed_count;
-  char *dt_strtab;
+  char * dt_strtab;
+  size_t dt_strsz;
   elf_section_list * symtab_shndx_list;
   bfd_vma gp;                          /* The gp value */
   unsigned int gp_size;                        /* The gp size */
index fa8881e8ea69fc9473ca5d47f1507571aa78d693..2bd236b405aad151fb4bac4e9259f949670ccd5a 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2102,9 +2102,11 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
     goto error_return;
 
   /* Dynamic string table must be valid until ABFD is closed.  */
-  strbuf = (char *) _bfd_alloc_and_read (abfd, dt_strsz, dt_strsz);
+  strbuf = (char *) _bfd_alloc_and_read (abfd, dt_strsz + 1, dt_strsz);
   if (strbuf == NULL)
     goto error_return;
+  /* Since this is a string table, make sure that it is terminated.  */
+  strbuf[dt_strsz] = 0;
 
   /* Get the real symbol count from DT_HASH or DT_GNU_HASH.  Prefer
      DT_HASH since it is simpler than DT_GNU_HASH.  */
@@ -2356,6 +2358,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
 
  empty_gnu_hash:
   elf_tdata (abfd)->dt_strtab = strbuf;
+  elf_tdata (abfd)->dt_strsz = dt_strsz;
   elf_tdata (abfd)->dt_symtab = isymbuf;
   elf_tdata (abfd)->dt_symtab_count = symcount;
   elf_tdata (abfd)->dt_versym = versym;
@@ -9396,6 +9399,7 @@ bool
 _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 {
   bfd_byte *contents = NULL;
+  bool free_contents = false;
   unsigned int freeidx = 0;
   size_t amt;
 
@@ -9438,6 +9442,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
          if (contents == NULL)
            goto error_return_verref;
 
+         free_contents = true;
          verneed_size = hdr->sh_size;
          verneed_count = hdr->sh_info;
        }
@@ -9471,8 +9476,13 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
          iverneed->vn_bfd = abfd;
 
          if (elf_use_dt_symtab_p (abfd))
-           iverneed->vn_filename
-             = elf_tdata (abfd)->dt_strtab + iverneed->vn_file;
+           {
+             if (iverneed->vn_file < elf_tdata (abfd)->dt_strsz)
+               iverneed->vn_filename
+                 = elf_tdata (abfd)->dt_strtab + iverneed->vn_file;
+             else
+               iverneed->vn_filename = NULL;
+           }   
          else
            iverneed->vn_filename
              = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
@@ -9508,8 +9518,13 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
              _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
 
              if (elf_use_dt_symtab_p (abfd))
-               ivernaux->vna_nodename
-                 = elf_tdata (abfd)->dt_strtab + ivernaux->vna_name;
+               {
+                 if (ivernaux->vna_name < elf_tdata (abfd)->dt_strsz)
+                   ivernaux->vna_nodename
+                     = elf_tdata (abfd)->dt_strtab + ivernaux->vna_name;
+                 else
+                   ivernaux->vna_nodename = NULL;
+               }
              else
                ivernaux->vna_nodename
                  = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
@@ -9703,8 +9718,13 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
              _bfd_elf_swap_verdaux_in (abfd, everdaux, iverdaux);
 
              if (elf_use_dt_symtab_p (abfd))
-               iverdaux->vda_nodename
-                 = elf_tdata (abfd)->dt_strtab + iverdaux->vda_name;
+               {
+                 if (iverdaux->vda_name < elf_tdata (abfd)->dt_strsz)
+                   iverdaux->vda_nodename
+                     = elf_tdata (abfd)->dt_strtab + iverdaux->vda_name;
+                 else
+                   iverdaux->vda_nodename = NULL;
+               }
              else
                iverdaux->vda_nodename
                  = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
@@ -9799,7 +9819,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
   return true;
 
  error_return:
-  free (contents);
+  if (free_contents)
+    free (contents);
   return false;
 }
 \f