]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Don't have first_hash entries of strings that can be freed.
authorAlan Modra <amodra@gmail.com>
Sat, 6 Apr 2024 05:19:44 +0000 (15:49 +1030)
committerAlan Modra <amodra@gmail.com>
Sat, 6 Apr 2024 06:05:35 +0000 (16:35 +1030)
Seen running "LTO 1" under valgrind.
==1443263== Invalid read of size 1
==1443263==    at 0x484CFE4: strcmp (vg_replace_strmem.c:939)
==1443263==    by 0x56E16C: bfd_hash_lookup (hash.c:564)
==1443263==    by 0x5A3C8F: elf_link_add_to_first_hash (elflink.c:4316)
==1443263==    by 0x5AE60F: elf_link_add_object_symbols (elflink.c:5663)
==1443263==    by 0x5B0672: bfd_elf_link_add_symbols (elflink.c:6333)
==1443263==    by 0x41448F: load_symbols (ldlang.c:3129)
==1443263==    by 0x4149D8: open_input_bfds (ldlang.c:3621)
==1443263==    by 0x414968: open_input_bfds (ldlang.c:3569)
==1443263==    by 0x4166A2: lang_process (ldlang.c:8162)
==1443263==    by 0x4194D5: main (ldmain.c:504)
==1443263==  Address 0x525e230 is 192 bytes inside a block of size 4,064 free'd
==1443263==    at 0x484810F: free (vg_replace_malloc.c:974)
==1443263==    by 0x8D4D87: objalloc_free_block (objalloc.c:248)
==1443263==    by 0x5AEACC: elf_link_add_object_symbols (elflink.c:5790)
==1443263==    by 0x5B0672: bfd_elf_link_add_symbols (elflink.c:6333)
==1443263==    by 0x41448F: load_symbols (ldlang.c:3129)
==1443263==    by 0x4149D8: open_input_bfds (ldlang.c:3621)
==1443263==    by 0x414968: open_input_bfds (ldlang.c:3569)
==1443263==    by 0x4166A2: lang_process (ldlang.c:8162)
==1443263==    by 0x4194D5: main (ldmain.c:504)

PR ld/31482
PR ld/31489
* elflink.c (elf_link_add_to_first_hash): Add "copy" param.
(elf_link_add_object_symbols): Flag that name must be copied
when appending version string to symbol name.

bfd/elflink.c

index e41b3d6dad79d2786a17cf65bf5db6deadfa6341..dadac2522d5839be0c65e2018199adb634641b08 100644 (file)
@@ -4304,7 +4304,7 @@ elf_link_first_hash_newfunc (struct bfd_hash_entry *entry,
 
 static void
 elf_link_add_to_first_hash (bfd *abfd, struct bfd_link_info *info,
-                           const char *name)
+                           const char *name, bool copy)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
   /* Skip if there is no first hash.  */
@@ -4313,7 +4313,7 @@ elf_link_add_to_first_hash (bfd *abfd, struct bfd_link_info *info,
 
   struct elf_link_first_hash_entry *e
     = ((struct elf_link_first_hash_entry *)
-       bfd_hash_lookup (htab->first_hash, name, true, false));
+       bfd_hash_lookup (htab->first_hash, name, true, copy));
   if (e == NULL)
     info->callbacks->einfo
       (_("%F%P: %pB: failed to add %s to first hash\n"), abfd, name);
@@ -4920,6 +4920,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       asection *sec, *new_sec;
       flagword flags;
       const char *name;
+      bool must_copy_name = false;
       struct elf_link_hash_entry *h;
       struct elf_link_hash_entry *hi;
       bool definition;
@@ -5217,6 +5218,11 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              memcpy (p, verstr, verlen + 1);
 
              name = newname;
+             /* Since bfd_hash_alloc is used for "name", the string
+                must be copied if added to first_hash.  The string
+                memory can be freed when an --as-needed library is
+                not needed.  */
+             must_copy_name = true;
            }
 
          /* If this symbol has default visibility and the user has
@@ -5660,7 +5666,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                       && h->root.u.def.section->owner == abfd)
                /* Add this symbol to first hash if this shared
                   object has the first definition.  */
-               elf_link_add_to_first_hash (abfd, info, name);
+               elf_link_add_to_first_hash (abfd, info, name, must_copy_name);
            }
        }
     }
@@ -6108,7 +6114,7 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd,
     {
       /* Add this symbol to first hash if this archive has the first
         definition.  */
-      elf_link_add_to_first_hash (abfd, info, name);
+      elf_link_add_to_first_hash (abfd, info, name, false);
       return h;
     }