bfd_get_symbol_leading_char vs. ""
authorAlan Modra <amodra@gmail.com>
Tue, 22 Aug 2023 11:43:41 +0000 (21:13 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 23 Aug 2023 00:37:45 +0000 (10:07 +0930)
Some places matching the first char of a string against
bfd_get_symbol_leading_char, which may be zero, didn't check for the
string being "".  This patch adds the check to stop accesses past the
end of the string and potential buffer overruns.
The dlltool one was found by oss-fuzz quite a while ago.

bfd/
* cofflink.c (_bfd_coff_link_input_bfd): Ensure a zero
bfd_get_symbol_leading_char doesn't lead to accessing past the
zero string terminator.
* linker.c (bfd_wrapped_link_hash_lookup): Likewise.
(unwrap_hash_lookup): Likewise.
binutils/
* dlltool.c (scan_filtered_symbols): Ensure a zero
bfd_get_symbol_leading_char doesn't lead to accessing past the
zero string terminator.

bfd/cofflink.c
bfd/linker.c
binutils/dlltool.c

index aea5c4c38a50b197c80a34969af3ecdd8b514c07..221f6e8183a325d58740dd0a47a24a3c074d7353 100644 (file)
@@ -1618,7 +1618,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
          /* Ignore fake names invented by compiler; treat them all as
             the same name.  */
          if (*name == '~' || *name == '.' || *name == '$'
-             || (*name == bfd_get_symbol_leading_char (input_bfd)
+             || (*name
+                 && *name == bfd_get_symbol_leading_char (input_bfd)
                  && (name[1] == '~' || name[1] == '.' || name[1] == '$')))
            name = "";
 
index 0f4f9a1776c51dfd36f6af9d0c80b3dc60361d7a..28fffc3ad6319ebb5fd1856e2c0507d028ba742d 100644 (file)
@@ -544,7 +544,9 @@ bfd_wrapped_link_hash_lookup (bfd *abfd,
       char prefix = '\0';
 
       l = string;
-      if (*l == bfd_get_symbol_leading_char (abfd) || *l == info->wrap_char)
+      if (*l
+         && (*l == bfd_get_symbol_leading_char (abfd)
+             || *l == info->wrap_char))
        {
          prefix = *l;
          ++l;
@@ -621,8 +623,9 @@ unwrap_hash_lookup (struct bfd_link_info *info,
 {
   const char *l = h->root.string;
 
-  if (*l == bfd_get_symbol_leading_char (input_bfd)
-      || *l == info->wrap_char)
+  if (*l
+      && (*l == bfd_get_symbol_leading_char (input_bfd)
+         || *l == info->wrap_char))
     ++l;
 
   if (startswith (l, WRAP))
index 085d4c2ce4114be87da4b4a4c919fcde44dfb550..6d63e11e08427d188063cd4a1e20477e7bc1f85c 100644 (file)
@@ -1500,7 +1500,8 @@ scan_filtered_symbols (bfd *abfd, void *minisyms, long symcount,
        bfd_fatal (bfd_get_filename (abfd));
 
       symbol_name = bfd_asymbol_name (sym);
-      if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
+      if (*symbol_name
+         && *symbol_name == bfd_get_symbol_leading_char (abfd))
        ++symbol_name;
 
       def_exports (xstrdup (symbol_name) , 0, -1, 0, 0,