mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-27 14:00:30 +00:00
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.
This commit is contained in:
parent
877a8638ba
commit
0897ec1581
@ -7,6 +7,14 @@
|
||||
* addr2line.c (slurp_symtab): If the symcount is zero, free the
|
||||
symbol table pointer.
|
||||
|
||||
* 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.
|
||||
|
||||
2015-01-23 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* nlmconv.c (powerpc_mangle_relocs): Fix build errors introduced
|
||||
|
@ -1887,12 +1887,12 @@ sizednumexpr:
|
||||
}
|
||||
| sizednumexpr '/' sizednumexpr
|
||||
{
|
||||
$$.val = $1.val / $3.val;
|
||||
$$.val = $1.val / ($3.val ? $3.val : 1);
|
||||
$$.dword = $1.dword || $3.dword;
|
||||
}
|
||||
| sizednumexpr '%' sizednumexpr
|
||||
{
|
||||
$$.val = $1.val % $3.val;
|
||||
$$.val = $1.val % ($3.val ? $3.val : 1);
|
||||
$$.dword = $1.dword || $3.dword;
|
||||
}
|
||||
| sizednumexpr '+' sizednumexpr
|
||||
@ -1966,12 +1966,13 @@ sizedposnumexpr:
|
||||
}
|
||||
| sizedposnumexpr '/' sizednumexpr
|
||||
{
|
||||
$$.val = $1.val / $3.val;
|
||||
$$.val = $1.val / ($3.val ? $3.val : 1);
|
||||
$$.dword = $1.dword || $3.dword;
|
||||
}
|
||||
| sizedposnumexpr '%' sizednumexpr
|
||||
{
|
||||
$$.val = $1.val % $3.val;
|
||||
/* PR 17512: file: 89105a25. */
|
||||
$$.val = $1.val % ($3.val ? $3.val : 1);
|
||||
$$.dword = $1.dword || $3.dword;
|
||||
}
|
||||
| sizedposnumexpr '+' sizednumexpr
|
||||
|
@ -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;
|
||||
|
102
binutils/resrc.c
102
binutils/resrc.c
@ -2932,53 +2932,63 @@ write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data)
|
||||
if (length < BIN_MESSAGETABLE_SIZE)
|
||||
has_error = 1;
|
||||
else
|
||||
do {
|
||||
rc_uint_type m, i;
|
||||
mt = (const struct bin_messagetable *) data;
|
||||
m = windres_get_32 (&wrtarget, mt->cblocks, length);
|
||||
if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
|
||||
{
|
||||
has_error = 1;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
rc_uint_type low, high, offset;
|
||||
const struct bin_messagetable_item *mti;
|
||||
do
|
||||
{
|
||||
rc_uint_type m, i;
|
||||
|
||||
mt = (const struct bin_messagetable *) data;
|
||||
m = windres_get_32 (&wrtarget, mt->cblocks, length);
|
||||
|
||||
if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
|
||||
{
|
||||
has_error = 1;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
rc_uint_type low, high, offset;
|
||||
const struct bin_messagetable_item *mti;
|
||||
|
||||
low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
|
||||
high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
|
||||
offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
|
||||
while (low <= high)
|
||||
{
|
||||
rc_uint_type elen, flags;
|
||||
if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
|
||||
{
|
||||
has_error = 1;
|
||||
break;
|
||||
}
|
||||
mti = (const struct bin_messagetable_item *) &data[offset];
|
||||
elen = windres_get_16 (&wrtarget, mti->length, 2);
|
||||
flags = windres_get_16 (&wrtarget, mti->flags, 2);
|
||||
if ((offset + elen) > length)
|
||||
{
|
||||
has_error = 1;
|
||||
break;
|
||||
}
|
||||
wr_printcomment (e, "MessageId = 0x%x", low);
|
||||
wr_printcomment (e, "");
|
||||
|
||||
/* PR 17512: file: 5c3232dc. */
|
||||
if (elen)
|
||||
{
|
||||
if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
|
||||
unicode_print (e, (const unichar *) mti->data,
|
||||
(elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
|
||||
else
|
||||
ascii_print (e, (const char *) mti->data,
|
||||
(elen - BIN_MESSAGETABLE_ITEM_SIZE));
|
||||
}
|
||||
wr_printcomment (e,"");
|
||||
++low;
|
||||
offset += elen;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
|
||||
high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
|
||||
offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
|
||||
while (low <= high)
|
||||
{
|
||||
rc_uint_type elen, flags;
|
||||
if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
|
||||
{
|
||||
has_error = 1;
|
||||
break;
|
||||
}
|
||||
mti = (const struct bin_messagetable_item *) &data[offset];
|
||||
elen = windres_get_16 (&wrtarget, mti->length, 2);
|
||||
flags = windres_get_16 (&wrtarget, mti->flags, 2);
|
||||
if ((offset + elen) > length)
|
||||
{
|
||||
has_error = 1;
|
||||
break;
|
||||
}
|
||||
wr_printcomment (e, "MessageId = 0x%x", low);
|
||||
wr_printcomment (e, "");
|
||||
if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
|
||||
unicode_print (e, (const unichar *) mti->data,
|
||||
(elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
|
||||
else
|
||||
ascii_print (e, (const char *) mti->data,
|
||||
(elen - BIN_MESSAGETABLE_ITEM_SIZE));
|
||||
wr_printcomment (e,"");
|
||||
++low;
|
||||
offset += elen;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
if (has_error)
|
||||
wr_printcomment (e, "Illegal data");
|
||||
wr_print_flush (e);
|
||||
|
Loading…
Reference in New Issue
Block a user