[binutils-gdb/binutils-2_46-branch] PR 34204 dlltool SEGVs with --exclude-symbols

Alan Modra via Binutils-cvs <[email protected]> Wed, 10 Jun 2026 07:24:27 +0000 (GMT)
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2c77fbc70079dd5df66433dce6e287e49e46a4c4

commit 2c77fbc70079dd5df66433dce6e287e49e46a4c4
Author: Alan Modra <[email protected]>
Date:   Wed Jun 10 11:40:59 2026 +0930

    PR 34204 dlltool SEGVs with --exclude-symbols
    
    This fixes a segfault introduced by commit 45a7f5a29de7 which didn't
    take into account that there was a use of leading_underscore in option
    processing.
    
            PR 34204
            * dlltool.c (struct string_list): Make string a flexible array
            member.
            (add_excludes): Adjust to suit.  Extract code adding underscore
            and informing..
            (underscore_excludes): ..to here.  New function.
            (main): Call underscore_excludes.
    
    (cherry picked from commit 500390720267e2f009f0354e5051fa2e176b143d)

Diff:
---
 binutils/dlltool.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index 94805fcd334..fa8bdd78bc5 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -789,7 +789,7 @@ export_type;
 struct string_list
 {
   struct string_list *next;
-  char *string;
+  char string[];
 };
 
 static struct string_list *excludes;
@@ -1460,23 +1460,37 @@ add_excludes (const char *new_excludes)
   exclude_string = strtok (local_copy, ",:");
   for (; exclude_string; exclude_string = strtok (NULL, ",:"))
     {
-      struct string_list *new_exclude = xmalloc (sizeof (*new_exclude));
-      /* Don't add a leading underscore for fastcall symbols.  */
-      if (*exclude_string == '@')
-	new_exclude->string = xstrdup (exclude_string);
-      else
-	new_exclude->string = xasprintf ("%s%s", leading_underscore,
-					 exclude_string);
+      size_t len = strlen (exclude_string);
+      /* Allocate extra byte for possible underscore.  */
+      struct string_list *new_exclude = xmalloc (sizeof (*new_exclude)
+						 + len + 2);
+      memcpy (new_exclude->string, exclude_string, len + 1);
       new_exclude->next = excludes;
       excludes = new_exclude;
-
-      /* xgettext:c-format */
-      inform (_("Excluding symbol: %s"), exclude_string);
     }
 
   free (local_copy);
 }
 
+/* Prefix symbols on the excludes list with an underscore.  */
+
+static void
+underscore_excludes (void)
+{
+  for (struct string_list *ex = excludes; ex; ex = ex->next)
+    {
+      /* Don't add a leading underscore for fastcall symbols.  */
+      if (*ex->string != '@' && *leading_underscore)
+	{
+	  size_t len = strlen (ex->string);
+	  memmove (ex->string + 1, ex->string, len + 1);
+	  *ex->string = *leading_underscore;
+	}
+      /* xgettext:c-format */
+      inform (_("Excluding symbol: %s"), ex->string);
+    }
+}
+
 /* See if STRING is on the list of symbols to exclude.  */
 
 static bool
@@ -4053,6 +4067,8 @@ main (int ac, char **av)
   if (do_default_excludes)
     set_default_excludes ();
 
+  underscore_excludes ();
+
   if (def_file)
     process_def_file (def_file);