aboutsummaryrefslogtreecommitdiff
path: root/binutils/rescoff.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-01-27 17:32:23 +0000
committerNick Clifton <nickc@redhat.com>2015-01-27 17:32:23 +0000
commit0897ec15810bca3420ea7b8a91e491ed45780202 (patch)
treedd7cc451877a5826e06000613f5d8bbf6b46e85e /binutils/rescoff.c
parent877a8638ba563c667eb5358240334c473d0573a1 (diff)
downloadgdb-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.c22
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;