diff options
author | Nick Clifton <nickc@redhat.com> | 2015-01-27 17:32:23 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-01-27 17:32:23 +0000 |
commit | 0897ec15810bca3420ea7b8a91e491ed45780202 (patch) | |
tree | dd7cc451877a5826e06000613f5d8bbf6b46e85e /binutils/resrc.c | |
parent | 877a8638ba563c667eb5358240334c473d0573a1 (diff) | |
download | gdb-0897ec15810bca3420ea7b8a91e491ed45780202.zip gdb-0897ec15810bca3420ea7b8a91e491ed45780202.tar.gz gdb-0897ec15810bca3420ea7b8a91e491ed45780202.tar.bz2 |
Fixes for invalid memory accesses triggered by running windres on corrupt binaries.
PR binutils/17512
* rcparse.y: Add checks to avoid integer divide by zero.
* rescoff.c (read_coff_rsrc): Add check on the size of the
resource section.
(read_coff_res_dir): Add check on the nesting level.
Check for resource names overrunning the buffer.
* resrc.c (write_rc_messagetable): Update formatting.
Add check of 'elen' being zero.
Diffstat (limited to 'binutils/resrc.c')
-rw-r--r-- | binutils/resrc.c | 102 |
1 files changed, 56 insertions, 46 deletions
diff --git a/binutils/resrc.c b/binutils/resrc.c index 4e0b24c..f0cacd1 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -2932,53 +2932,63 @@ write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data) if (length < BIN_MESSAGETABLE_SIZE) has_error = 1; else - do { - rc_uint_type m, i; - mt = (const struct bin_messagetable *) data; - m = windres_get_32 (&wrtarget, mt->cblocks, length); - if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) - { - has_error = 1; - break; - } - for (i = 0; i < m; i++) - { - rc_uint_type low, high, offset; - const struct bin_messagetable_item *mti; + do + { + rc_uint_type m, i; + + mt = (const struct bin_messagetable *) data; + m = windres_get_32 (&wrtarget, mt->cblocks, length); + + if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) + { + has_error = 1; + break; + } + for (i = 0; i < m; i++) + { + rc_uint_type low, high, offset; + const struct bin_messagetable_item *mti; + + low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); + high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); + offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); + while (low <= high) + { + rc_uint_type elen, flags; + if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) + { + has_error = 1; + break; + } + mti = (const struct bin_messagetable_item *) &data[offset]; + elen = windres_get_16 (&wrtarget, mti->length, 2); + flags = windres_get_16 (&wrtarget, mti->flags, 2); + if ((offset + elen) > length) + { + has_error = 1; + break; + } + wr_printcomment (e, "MessageId = 0x%x", low); + wr_printcomment (e, ""); + + /* PR 17512: file: 5c3232dc. */ + if (elen) + { + if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) + unicode_print (e, (const unichar *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); + else + ascii_print (e, (const char *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE)); + } + wr_printcomment (e,""); + ++low; + offset += elen; + } + } + } + while (0); - low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); - high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); - offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); - while (low <= high) - { - rc_uint_type elen, flags; - if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) - { - has_error = 1; - break; - } - mti = (const struct bin_messagetable_item *) &data[offset]; - elen = windres_get_16 (&wrtarget, mti->length, 2); - flags = windres_get_16 (&wrtarget, mti->flags, 2); - if ((offset + elen) > length) - { - has_error = 1; - break; - } - wr_printcomment (e, "MessageId = 0x%x", low); - wr_printcomment (e, ""); - if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) - unicode_print (e, (const unichar *) mti->data, - (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); - else - ascii_print (e, (const char *) mti->data, - (elen - BIN_MESSAGETABLE_ITEM_SIZE)); - wr_printcomment (e,""); - ++low; - offset += elen; - } - } - } while (0); if (has_error) wr_printcomment (e, "Illegal data"); wr_print_flush (e); |