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/rescoff.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/rescoff.c')
-rw-r--r-- | binutils/rescoff.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/binutils/rescoff.c b/binutils/rescoff.c index 0004c3a..3e63e49 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -142,8 +142,14 @@ read_coff_rsrc (const char *filename, const char *target) set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD); size = bfd_section_size (abfd, sec); - data = (bfd_byte *) res_alloc (size); + /* PR 17512: file: 1b25ba5d + The call to get_file_size here may be expensive + but there is no other way to determine if the section size + is reasonable. */ + if (size > (bfd_size_type) get_file_size (filename)) + fatal (_("%s: .rsrc section is bigger than the file!"), filename); + data = (bfd_byte *) res_alloc (size); get_windres_bfd_content (&wrbfd, data, 0, size); flaginfo.filename = filename; @@ -185,6 +191,13 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, rc_res_entry **pp; const struct extern_res_entry *ere; + /* PR 17512: file: 09d80f53. + Whilst in theory resources can nest to any level, in practice + Microsoft only defines 3 levels. Corrupt files however might + claim to use more. */ + if (level > 4) + overrun (flaginfo, _("Resources nest too deep")); + if ((size_t) (flaginfo->data_end - data) < sizeof (struct extern_res_directory)) overrun (flaginfo, _("directory")); @@ -234,7 +247,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, re->id.u.n.length = length; re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar)); for (j = 0; j < length; j++) - re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); + { + /* PR 17512: file: 05dc4a16. */ + if (length < 0 || ers >= (bfd_byte *) ere || ers + j * 2 + 4 >= (bfd_byte *) ere) + overrun (flaginfo, _("resource name")); + re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); + } if (level == 0) type = &re->id; |