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 --git a/binutils/resbin.c b/binutils/resbin.c
index fa77cd4..02905b9 100644
--- a/binutils/resbin.c
+++ b/binutils/resbin.c
@@ -1060,8 +1060,14 @@
*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 @@
}
*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 @@
(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 @@
if (stverlen < sverlen)
{
non_fatal (_("unexpected version string length %ld < %ld"),
- (long) verlen, (long) sverlen);
+ (long) stverlen, (long) sverlen);
return NULL;
}
stverlen -= sverlen;