aboutsummaryrefslogtreecommitdiff
path: root/binutils/rescoff.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/rescoff.c')
-rw-r--r--binutils/rescoff.c88
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;
}