[binutils-gdb] windres: buffer overflow in bin_to_res_toolbar

Alan Modra amodra@sourceware.org
Mon Apr 14 21:29:40 GMT 2025


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

commit 4846e543de9543bff001f58d6a47097e0edd588d
Author: Alan Modra <amodra@gmail.com>
Date:   Mon Apr 14 10:31:32 2025 +0930

    windres: buffer overflow in bin_to_res_toolbar
    
    oss-fuzz testcase manages to hit a buffer overflow.  Sanity check
    by passing the buffer length to bin_to_res_toolbar and ensuring reads
    don't go off the end of the buffer.

Diff:
---
 binutils/resbin.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/binutils/resbin.c b/binutils/resbin.c
index 388b0162447..a42a846d94b 100644
--- a/binutils/resbin.c
+++ b/binutils/resbin.c
@@ -54,7 +54,7 @@ static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *
 static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type);
 static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type);
 static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type);
-static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *);
+static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type);
 static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *,
 				unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *,
 				rc_uint_type *);
@@ -105,7 +105,7 @@ bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data,
 	case RT_VERSION:
 	  return bin_to_res_version (wrbfd, data, length);
 	case RT_TOOLBAR:
-	  return  bin_to_res_toolbar (wrbfd, data);
+	  return bin_to_res_toolbar (wrbfd, data, length);
 
 	}
     }
@@ -1216,12 +1216,15 @@ bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
 }
 

 static rc_res_resource *
-bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data)
+bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data,
+		    rc_uint_type length)
 {
   rc_toolbar *ri;
   rc_res_resource *r;
   rc_uint_type i;
 
+  if (length < 12)
+    toosmall (_("toolbar"));
   ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
   ri->button_width = windres_get_32 (wrbfd, data, 4);
   ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
@@ -1229,14 +1232,18 @@ bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data)
   ri->items = NULL;
 
   data += 12;
-  for (i=0 ; i < ri->nitems; i++)
+  length -= 12;
+  for (i = 0; i < ri->nitems; i++)
   {
     rc_toolbar_item *it;
     it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item));
     it->id.named = 0;
+    if (length < 4)
+      toosmall (_("toolbar item"));
     it->id.u.id = (int) windres_get_32 (wrbfd, data, 4);
     it->prev = it->next = NULL;
     data += 4;
+    length -= 4;
     if(ri->items) {
       rc_toolbar_item *ii = ri->items;
       while (ii->next != NULL)


More information about the Binutils-cvs mailing list