[binutils-gdb] Sanity check windows resource version len

Alan Modra amodra@sourceware.org
Sun Aug 17 13:25:58 GMT 2025


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

commit a5858e81363051a818ea163d52f62d8251097d11
Author: Alan Modra <amodra@gmail.com>
Date:   Sun Aug 17 21:34:17 2025 +0930

    Sanity check windows resource version len
    
    oss-fuzz generated a total length field of 32, when the header was 40
    bytes.  Subtracting gave -8ul for the remaining length..
    
    I think we should be sanity checking the total length given in the
    header against the remaining buffer length and the size of the header
    each time get_version_header is called.
    
    Possibly vallen should be sanity checked inside get_version_header
    too, but I'll leave that to someone else.
    
            PR 27686
            * resbin.c (bin_to_res_version): Correct error message arg.
            Move len vs. buffer length sanity check..
            (get_version_header): ..to here.  Also sanity check len
            against off.

Diff:
---
 binutils/resbin.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/binutils/resbin.c b/binutils/resbin.c
index fa77cd43d23..02905b9c9de 100644
--- a/binutils/resbin.c
+++ b/binutils/resbin.c
@@ -1060,8 +1060,14 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data,
   *vallen = windres_get_16 (wrbfd, data + 2);
   *type = windres_get_16 (wrbfd, data + 4);
 
-  *off = 6;
+  if (*len > length)
+    {
+      non_fatal (_("version length %lu greater than resource length %lu"),
+		 (unsigned long) *len, (unsigned long) length);
+      return false;
+    }
 
+  *off = 6;
   length -= 6;
   data += 6;
 
@@ -1101,6 +1107,14 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data,
     }
 
   *off = (*off + 3) &~ 3;
+
+  if (*len < *off)
+    {
+      non_fatal (_("version length %lu does not cover header length %lu"),
+		 (unsigned long) *len, (unsigned long) *off);
+      return false;
+    }
+
   return true;
 }
 
@@ -1120,14 +1134,6 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data,
 			   (unichar **) NULL, &verlen, &vallen, &type, &off))
     return NULL;
 
-  /* PR 17512: The verlen field does not include padding length.  */
-  if (verlen > length)
-    {
-      non_fatal (_("version length %lu greater than resource length %lu"),
-		 (unsigned long) verlen, (unsigned long) length);
-      return NULL;
-    }
-
   if (type != 0)
     {
       non_fatal (_("unexpected version type %d"), (int) type);
@@ -1311,7 +1317,7 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data,
 		  if (stverlen < sverlen)
 		    {
 		      non_fatal (_("unexpected version string length %ld < %ld"),
-				 (long) verlen, (long) sverlen);
+				 (long) stverlen, (long) sverlen);
 		      return NULL;
 		    }
 		  stverlen -= sverlen;


More information about the Binutils-cvs mailing list