diff options
Diffstat (limited to 'binutils/rescoff.c')
-rw-r--r-- | binutils/rescoff.c | 88 |
1 files changed, 60 insertions, 28 deletions
diff --git a/binutils/rescoff.c b/binutils/rescoff.c index 98e5eb0..6031602 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -138,12 +138,14 @@ read_coff_rsrc (const char *filename, const char *target) if (bfd_get_error () == bfd_error_file_ambiguously_recognized) list_matching_formats (matching); free (matching); + bfd_close (abfd); return NULL; } if (bfd_get_flavour (abfd) != bfd_target_coff_flavour || !obj_pe (abfd)) { non_fatal (_("%s: not a PE file"), filename); + bfd_close (abfd); return NULL; } @@ -151,6 +153,7 @@ read_coff_rsrc (const char *filename, const char *target) if (sec == NULL) { non_fatal (_("%s: no resource section"), filename); + bfd_close (abfd); return NULL; } @@ -163,6 +166,7 @@ read_coff_rsrc (const char *filename, const char *target) if (size > (bfd_size_type) get_file_size (filename)) { non_fatal (_("%s: .rsrc section is bigger than the file!"), filename); + bfd_close (abfd); return NULL; } @@ -218,7 +222,8 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, return NULL; } - if ((size_t) (flaginfo->data_end - data) < sizeof (struct extern_res_directory)) + size_t data_len = flaginfo->data_end - data; + if (data_len < sizeof (struct extern_res_directory)) { overrun (flaginfo, _("directory")); return NULL; @@ -249,7 +254,8 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, const bfd_byte *ers; int length, j; - if ((const bfd_byte *) ere >= flaginfo->data_end) + if ((const bfd_byte *) ere > flaginfo->data_end + || flaginfo->data_end - (const bfd_byte *) ere < 8) { overrun (flaginfo, _("named directory entry")); return NULL; @@ -261,31 +267,32 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, /* For some reason the high bit in NAME is set. */ name &=~ 0x80000000; - if (name > (rc_uint_type) (flaginfo->data_end - flaginfo->data)) + if (name > data_len) { overrun (flaginfo, _("directory entry name")); return NULL; } ers = flaginfo->data + name; - + if (flaginfo->data_end - ers < 2) + { + overrun (flaginfo, _("resource name")); + return NULL; + } + length = windres_get_16 (wrbfd, ers, 2); + /* PR 17512: file: 05dc4a16. */ + if (length * 2 + 4 > flaginfo->data_end - ers) + { + overrun (flaginfo, _("resource name")); + return NULL; + } re = (rc_res_entry *) res_alloc (sizeof *re); re->next = NULL; re->id.named = 1; - length = windres_get_16 (wrbfd, ers, 2); re->id.u.n.length = length; re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar)); for (j = 0; j < length; j++) - { - /* PR 17512: file: 05dc4a16. */ - if (length < 0 || ers >= flaginfo->data_end - || ers + j * 2 + 4 >= flaginfo->data_end) - { - overrun (flaginfo, _("resource name")); - return NULL; - } - re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); - } + re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); if (level == 0) type = &re->id; @@ -293,24 +300,25 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, if ((rva & 0x80000000) != 0) { rva &=~ 0x80000000; - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) + if (rva >= data_len) { overrun (flaginfo, _("named subdirectory")); return NULL; } re->subdir = 1; - re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, - level + 1); + re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, + type, level + 1); } else { - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) + if (rva >= data_len) { overrun (flaginfo, _("named resource")); return NULL; } re->subdir = 0; - re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); + re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, + flaginfo, type); } *pp = re; @@ -322,7 +330,8 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, unsigned long name, rva; rc_res_entry *re; - if ((const bfd_byte *) ere >= flaginfo->data_end) + if ((const bfd_byte *) ere > flaginfo->data_end + || flaginfo->data_end - (const bfd_byte *) ere < 8) { overrun (flaginfo, _("ID directory entry")); return NULL; @@ -342,24 +351,25 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, if ((rva & 0x80000000) != 0) { rva &=~ 0x80000000; - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) + if (rva >= data_len) { overrun (flaginfo, _("ID subdirectory")); return NULL; } re->subdir = 1; - re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, - level + 1); + re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, + type, level + 1); } else { - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) + if (rva >= data_len) { overrun (flaginfo, _("ID resource")); return NULL; } re->subdir = 0; - re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); + re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, + flaginfo, type); } *pp = re; @@ -522,6 +532,7 @@ write_coff_file (const char *filename, const char *target, if (! bfd_set_format (abfd, bfd_object)) { bfd_nonfatal ("bfd_set_format"); + bfd_close_all_done (abfd); return false; } @@ -529,24 +540,28 @@ write_coff_file (const char *filename, const char *target, if (! bfd_set_arch_mach (abfd, bfd_arch_sh, 0)) { bfd_nonfatal ("bfd_set_arch_mach(sh)"); + bfd_close_all_done (abfd); return false; } #elif defined DLLTOOL_MIPS if (! bfd_set_arch_mach (abfd, bfd_arch_mips, 0)) { bfd_nonfatal ("bfd_set_arch_mach(mips)"); + bfd_close_all_done (abfd); return false; } #elif defined DLLTOOL_ARM if (! bfd_set_arch_mach (abfd, bfd_arch_arm, 0)) { bfd_nonfatal ("bfd_set_arch_mach(arm)"); + bfd_close_all_done (abfd); return false; } #elif defined DLLTOOL_AARCH64 if (! bfd_set_arch_mach (abfd, bfd_arch_aarch64, 0)) { bfd_nonfatal ("bfd_set_arch_mach(aarch64)"); + bfd_close_all_done (abfd); return false; } #else @@ -554,6 +569,7 @@ write_coff_file (const char *filename, const char *target, if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0)) { bfd_nonfatal ("bfd_set_arch_mach(i386)"); + bfd_close_all_done (abfd); return false; } #endif @@ -561,6 +577,7 @@ write_coff_file (const char *filename, const char *target, if (! bfd_set_file_flags (abfd, HAS_SYMS | HAS_RELOC)) { bfd_nonfatal ("bfd_set_file_flags"); + bfd_close_all_done (abfd); return false; } @@ -570,12 +587,14 @@ write_coff_file (const char *filename, const char *target, if (sec == NULL) { bfd_nonfatal ("bfd_make_section"); + bfd_close_all_done (abfd); return false; } if (! bfd_set_symtab (abfd, &sec->symbol, 1)) { bfd_nonfatal ("bfd_set_symtab"); + bfd_close_all_done (abfd); return false; } @@ -622,7 +641,11 @@ write_coff_file (const char *filename, const char *target, /* Actually convert the resources to binary. */ if (!coff_to_bin (resources, &cwi)) - return false; + { + bfd_close_all_done (abfd); + free (cwi.relocs); + return false; + } /* Add another few bytes to the directory strings if needed for alignment. */ @@ -649,6 +672,8 @@ write_coff_file (const char *filename, const char *target, if (!bfd_set_section_size (sec, length)) { bfd_nonfatal ("bfd_set_section_size"); + bfd_close_all_done (abfd); + free (cwi.relocs); return false; } @@ -660,6 +685,8 @@ write_coff_file (const char *filename, const char *target, if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length)) { bfd_nonfatal ("bfd_set_section_contents"); + bfd_close_all_done (abfd); + free (cwi.relocs); return false; } offset += d->length; @@ -678,7 +705,11 @@ write_coff_file (const char *filename, const char *target, { if (res_to_bin (cwi.wrbfd, (rc_uint_type) offset, rd->res) == (rc_uint_type) -1) - return false; + { + bfd_close_all_done (abfd); + free (cwi.relocs); + return false; + } offset += rd->length; } @@ -687,6 +718,7 @@ write_coff_file (const char *filename, const char *target, if (! bfd_close (abfd)) { bfd_nonfatal ("bfd_close"); + free (cwi.relocs); return false; } |