X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Frescoff.c;h=9a0fcda2ac6ba4364350999d433bd70a4e24a61c;hb=0394eed15c5bf24943850f356785152c3d65ab94;hp=8799ea2bd46b2d1bb0847fcb6eee7cc2970740f6;hpb=57402f1e314550ef28cc63b16d5ac69270c02984;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/rescoff.c b/binutils/rescoff.c index 8799ea2bd4..9a0fcda2ac 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -1,6 +1,5 @@ /* rescoff.c -- read and write resources in Windows COFF files. - Copyright 1997, 1998, 1999, 2000, 2003, 2005, 2007, 2008 - Free Software Foundation, Inc. + Copyright (C) 1997-2019 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. Rewritten by Kai Tietz, Onevision. @@ -142,16 +141,22 @@ 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); + size = bfd_section_size (sec); + /* 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; flaginfo.data = data; flaginfo.data_end = data + size; - flaginfo.secaddr = (bfd_get_section_vma (abfd, sec) - - pe_data (abfd)->pe_opthdr.ImageBase); + flaginfo.secaddr = (bfd_section_vma (sec) + - pe_data (abfd)->pe_opthdr.ImageBase); /* Now just read in the top level resource directory. Note that we don't free data, since we create resource entries that point into @@ -159,7 +164,7 @@ read_coff_rsrc (const char *filename, const char *target) this will have to be cleaned up. */ ret = read_coff_res_dir (&wrbfd, data, &flaginfo, (const rc_res_id *) NULL, 0); - + bfd_close (abfd); return ret; @@ -186,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")); @@ -235,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 >= flaginfo->data_end || ers + j * 2 + 4 >= flaginfo->data_end) + 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; @@ -501,22 +518,22 @@ write_coff_file (const char *filename, const char *target, know the various offsets we will need. */ coff_bin_sizes (resources, &cwi); - /* Force the directory strings to be 32 bit aligned. Every other - structure is 32 bit aligned anyhow. */ - cwi.dirstrsize = (cwi.dirstrsize + 3) &~ 3; + /* Force the directory strings to be 64 bit aligned. Every other + structure is 64 bit aligned anyhow. */ + cwi.dirstrsize = (cwi.dirstrsize + 7) & ~7; /* Actually convert the resources to binary. */ coff_to_bin (resources, &cwi); - /* Add another 2 bytes to the directory strings if needed for + /* Add another few bytes to the directory strings if needed for alignment. */ - if ((cwi.dirstrs.length & 3) != 0) + if ((cwi.dirstrs.length & 7) != 0) { + rc_uint_type pad = 8 - (cwi.dirstrs.length & 7); bfd_byte *ex; - ex = coff_alloc (&cwi.dirstrs, 2); - ex[0] = 0; - ex[1] = 0; + ex = coff_alloc (& cwi.dirstrs, pad); + memset (ex, 0, pad); } /* Make sure that the data we built came out to the same size as we @@ -530,7 +547,7 @@ write_coff_file (const char *filename, const char *target, + cwi.dataentsize + cwi.resources.length); - if (! bfd_set_section_size (abfd, sec, length)) + if (!bfd_set_section_size (sec, length)) bfd_fatal ("bfd_set_section_size"); bfd_set_reloc (abfd, sec, cwi.relocs, cwi.reloc_count); @@ -741,10 +758,10 @@ coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) cwi->resources.last->next = d; cwi->resources.last = d; - cwi->resources.length += (d->length + 3) & ~3; + cwi->resources.length += (d->length + 7) & ~7; windres_put_32 (cwi->wrbfd, erd->size, d->length); - /* Force the next resource to have 32 bit alignment. */ - d->length = (d->length + 3) & ~3; + /* Force the next resource to have 64 bit alignment. */ + d->length = (d->length + 7) & ~7; }