[binutils-gdb] Fix CVE-2026-19582 - a potential buffer overflow in rsrc_resource_name.

Nick Clifton nickc@sourceware.org
Wed Sep 2 08:55:45 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=192afd3ce7c2324cdbee2d4646df6cf1e9b6fd09

commit 192afd3ce7c2324cdbee2d4646df6cf1e9b6fd09
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Sep 2 09:55:01 2026 +0100

    Fix CVE-2026-19582 - a potential buffer overflow in rsrc_resource_name.

Diff:
---
 bfd/peXXigen.c | 163 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 116 insertions(+), 47 deletions(-)

diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 9794ecdaabe..17a94c461fe 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -3811,92 +3811,152 @@ rsrc_cmp (bool is_name, rsrc_entry * a, rsrc_entry * b)
   return res;
 }
 
-static void
-rsrc_print_name (char * buffer, rsrc_string string)
+static bool
+rsrc_string_print_str (rsrc_string buffer, const char * format, char * context)
+{
+  if (buffer.string == NULL || buffer.len == 0)
+    return false;
+
+  int printed = snprintf ((char *) buffer.string, buffer.len, format, context);
+
+  if (printed >= (int) buffer.len)
+    {
+      buffer.len = 0;
+      return false;
+    }
+
+  buffer.string += printed;
+  buffer.len    -= printed;
+  return true;
+}
+
+static bool
+rsrc_string_print_int (rsrc_string buffer, const char * format, int context)
+{
+  if (buffer.string == NULL || buffer.len == 0)
+    return false;
+
+  int printed = snprintf ((char *) buffer.string, buffer.len, format, context);
+
+  if (printed >= (int) buffer.len)
+    {
+      buffer.len = 0;
+      return false;
+    }
+
+  buffer.string += printed;
+  buffer.len    -= printed;
+  return true;
+}
+
+static bool
+rsrc_print_name (rsrc_string buffer, rsrc_string string)
 {
   unsigned int  i;
   bfd_byte *    name = string.string;
 
   for (i = string.len; i--; name += 2)
-    sprintf (buffer + strlen (buffer), "%.1s", name);
+    {
+      if (! rsrc_string_print_str (buffer, "%.1s", (char *) name))
+	return false;
+    }
+
+  return true;
 }
 
-static const char *
-rsrc_resource_name (rsrc_entry *entry, rsrc_directory *dir, char *buffer)
+static bool
+rsrc_resource_name (rsrc_entry *entry, rsrc_directory *dir, rsrc_string buffer)
 {
   bool is_string = false;
+  bool res = true;
 
-  buffer[0] = 0;
+  if (buffer.string == NULL || buffer.len == 0)
+    return false;
+
+  buffer.string[0] = 0;
 
-  if (dir != NULL && dir->entry != NULL && dir->entry->parent != NULL
+  if (dir != NULL
+      && dir->entry != NULL
+      && dir->entry->parent != NULL
       && dir->entry->parent->entry != NULL)
     {
-      strcpy (buffer, "type: ");
+      res &= rsrc_string_print_str (buffer, "%s", "type: ");
+
       if (dir->entry->parent->entry->is_name)
-	rsrc_print_name (buffer + strlen (buffer),
-			 dir->entry->parent->entry->name_id.name);
+	{
+	  res &= rsrc_print_name (buffer, dir->entry->parent->entry->name_id.name);
+	}
       else
 	{
 	  unsigned int id = dir->entry->parent->entry->name_id.id;
 
-	  sprintf (buffer + strlen (buffer), "%x", id);
+	  res &= rsrc_string_print_int (buffer, "%x", id);
+
 	  switch (id)
 	    {
-	    case 1: strcat (buffer, " (CURSOR)"); break;
-	    case 2: strcat (buffer, " (BITMAP)"); break;
-	    case 3: strcat (buffer, " (ICON)"); break;
-	    case 4: strcat (buffer, " (MENU)"); break;
-	    case 5: strcat (buffer, " (DIALOG)"); break;
-	    case 6: strcat (buffer, " (STRING)"); is_string = true; break;
-	    case 7: strcat (buffer, " (FONTDIR)"); break;
-	    case 8: strcat (buffer, " (FONT)"); break;
-	    case 9: strcat (buffer, " (ACCELERATOR)"); break;
-	    case 10: strcat (buffer, " (RCDATA)"); break;
-	    case 11: strcat (buffer, " (MESSAGETABLE)"); break;
-	    case 12: strcat (buffer, " (GROUP_CURSOR)"); break;
-	    case 14: strcat (buffer, " (GROUP_ICON)"); break;
-	    case 16: strcat (buffer, " (VERSION)"); break;
-	    case 17: strcat (buffer, " (DLGINCLUDE)"); break;
-	    case 19: strcat (buffer, " (PLUGPLAY)"); break;
-	    case 20: strcat (buffer, " (VXD)"); break;
-	    case 21: strcat (buffer, " (ANICURSOR)"); break;
-	    case 22: strcat (buffer, " (ANIICON)"); break;
-	    case 23: strcat (buffer, " (HTML)"); break;
-	    case 24: strcat (buffer, " (MANIFEST)"); break;
-	    case 240: strcat (buffer, " (DLGINIT)"); break;
-	    case 241: strcat (buffer, " (TOOLBAR)"); break;
+	    case   1: res &= rsrc_string_print_str (buffer, "%s", " (CURSOR)"); break;
+	    case   2: res &= rsrc_string_print_str (buffer, "%s", " (BITMAP)"); break;
+	    case   3: res &= rsrc_string_print_str (buffer, "%s", " (ICON)"); break;
+	    case   4: res &= rsrc_string_print_str (buffer, "%s", " (MENU)"); break;
+	    case   5: res &= rsrc_string_print_str (buffer, "%s", " (DIALOG)"); break;
+	    case   6: res &= rsrc_string_print_str (buffer, "%s", " (STRING)"); is_string = true; break;
+	    case   7: res &= rsrc_string_print_str (buffer, "%s", " (FONTDIR)"); break;
+	    case   8: res &= rsrc_string_print_str (buffer, "%s", " (FONT)"); break;
+	    case   9: res &= rsrc_string_print_str (buffer, "%s", " (ACCELERATOR)"); break;
+	    case  10: res &= rsrc_string_print_str (buffer, "%s", " (RCDATA)"); break;
+	    case  11: res &= rsrc_string_print_str (buffer, "%s", " (MESSAGETABLE)"); break;
+	    case  12: res &= rsrc_string_print_str (buffer, "%s", " (GROUP_CURSOR)"); break;
+	    case  14: res &= rsrc_string_print_str (buffer, "%s", " (GROUP_ICON)"); break;
+	    case  16: res &= rsrc_string_print_str (buffer, "%s", " (VERSION)"); break;
+	    case  17: res &= rsrc_string_print_str (buffer, "%s", " (DLGINCLUDE)"); break;
+	    case  19: res &= rsrc_string_print_str (buffer, "%s", " (PLUGPLAY)"); break;
+	    case  20: res &= rsrc_string_print_str (buffer, "%s", " (VXD)"); break;
+	    case  21: res &= rsrc_string_print_str (buffer, "%s", " (ANICURSOR)"); break;
+	    case  22: res &= rsrc_string_print_str (buffer, "%s", " (ANIICON)"); break;
+	    case  23: res &= rsrc_string_print_str (buffer, "%s", " (HTML)"); break;
+	    case  24: res &= rsrc_string_print_str (buffer, "%s", " (MANIFEST)"); break;
+	    case 240: res &= rsrc_string_print_str (buffer, "%s", " (DLGINIT)"); break;
+	    case 241: res &= rsrc_string_print_str (buffer, "%s", " (TOOLBAR)"); break;
 	    }
 	}
     }
 
   if (dir != NULL && dir->entry != NULL)
     {
-      strcat (buffer, " name: ");
+      res &= rsrc_string_print_str (buffer, "%s", " name: ");
+
       if (dir->entry->is_name)
-	rsrc_print_name (buffer + strlen (buffer), dir->entry->name_id.name);
+	{
+	  res &= rsrc_print_name (buffer, dir->entry->name_id.name);
+	}
       else
 	{
 	  unsigned int id = dir->entry->name_id.id;
 
-	  sprintf (buffer + strlen (buffer), "%x", id);
+	  res &= rsrc_string_print_int (buffer, "%x", id);
 
 	  if (is_string)
-	    sprintf (buffer + strlen (buffer), " (resource id range: %d - %d)",
-		     (id - 1) << 4, (id << 4) - 1);
+	    {
+	      res &= rsrc_string_print_str (buffer, "%s", " (resource id range: ");
+	      res &= rsrc_string_print_int (buffer, "%d", (id - 1) << 4);
+	      res &= rsrc_string_print_str (buffer, "%s", " - ");
+	      res &= rsrc_string_print_int (buffer, "%d", (id << 4) - 1);
+	      res &= rsrc_string_print_str (buffer, "%s", ")");
+	    }
 	}
     }
 
   if (entry != NULL)
     {
-      strcat (buffer, " lang: ");
+      res &= rsrc_string_print_str (buffer, "%s", " lang: ");
 
       if (entry->is_name)
-	rsrc_print_name (buffer + strlen (buffer), entry->name_id.name);
+	res &= rsrc_print_name (buffer, entry->name_id.name);
       else
-	sprintf (buffer + strlen (buffer), "%x", entry->name_id.id);
+	res &= rsrc_string_print_int (buffer, "%x", entry->name_id.id);
     }
 
-  return buffer;
+  return res;
 }
 
 /* *sigh* Windows resource strings are special.  Only the top 28-bits of
@@ -4156,11 +4216,20 @@ rsrc_sort_entries (rsrc_dir_chain *chain,
 			_bfd_error_handler (_(".rsrc merge failure: duplicate leaf"));
 		      else
 			{
-			  char buff[256];
-
-			  _bfd_error_handler (_(".rsrc merge failure: duplicate leaf: %s"),
-					      rsrc_resource_name (entry, dir, buff));
+#define RSRC_RES_NAME_LEN 256
+			  char buff[RSRC_RES_NAME_LEN];
+			  rsrc_string buffer;
+
+			  buffer.string = (bfd_byte *) buff;
+			  buffer.len = RSRC_RES_NAME_LEN;
+
+			  if (rsrc_resource_name (entry, dir, buffer))
+			    _bfd_error_handler (_(".rsrc merge failure: duplicate leaf: %s"),
+						buffer.string);
+			  else
+			    _bfd_error_handler (_(".rsrc merge failure: duplicate leaf"));
 			}
+
 		      bfd_set_error (bfd_error_file_truncated);
 		      return;
 		    }


More information about the Binutils-cvs mailing list