Catch integer overflows/underflows when parsing corrupt DWARF FORM blocks.
PR 22895 PR 22893 * dwarf2.c (read_n_bytes): Replace size parameter with dwarf_block pointer. Drop unused abfd parameter. Check the size of the block before initialising the data field. Return the end pointer if the size is invalid. (read_attribute_value): Adjust invocations of read_n_bytes.
This commit is contained in:
parent
116acb2c26
commit
12c963421d
@ -5,6 +5,14 @@
|
||||
|
||||
2018-02-28 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR 22895
|
||||
PR 22893
|
||||
* dwarf2.c (read_n_bytes): Replace size parameter with dwarf_block
|
||||
pointer. Drop unused abfd parameter. Check the size of the block
|
||||
before initialising the data field. Return the end pointer if the
|
||||
size is invalid.
|
||||
(read_attribute_value): Adjust invocations of read_n_bytes.
|
||||
|
||||
PR 22894
|
||||
* dwarf1.c (parse_die): Check the length of form blocks before
|
||||
advancing the data pointer.
|
||||
|
36
bfd/dwarf2.c
36
bfd/dwarf2.c
@ -623,14 +623,24 @@ read_8_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
|
||||
}
|
||||
|
||||
static bfd_byte *
|
||||
read_n_bytes (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
bfd_byte *buf,
|
||||
bfd_byte *end,
|
||||
unsigned int size ATTRIBUTE_UNUSED)
|
||||
read_n_bytes (bfd_byte * buf,
|
||||
bfd_byte * end,
|
||||
struct dwarf_block * block)
|
||||
{
|
||||
if (buf + size > end)
|
||||
return NULL;
|
||||
return buf;
|
||||
unsigned int size = block->size;
|
||||
bfd_byte * block_end = buf + size;
|
||||
|
||||
if (block_end > end || block_end < buf)
|
||||
{
|
||||
block->data = NULL;
|
||||
block->size = 0;
|
||||
return end;
|
||||
}
|
||||
else
|
||||
{
|
||||
block->data = buf;
|
||||
return block_end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scans a NUL terminated string starting at BUF, returning a pointer to it.
|
||||
@ -1128,8 +1138,7 @@ read_attribute_value (struct attribute * attr,
|
||||
return NULL;
|
||||
blk->size = read_2_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 2;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk);
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
case DW_FORM_block4:
|
||||
@ -1139,8 +1148,7 @@ read_attribute_value (struct attribute * attr,
|
||||
return NULL;
|
||||
blk->size = read_4_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 4;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk);
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
case DW_FORM_data2:
|
||||
@ -1180,8 +1188,7 @@ read_attribute_value (struct attribute * attr,
|
||||
blk->size = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
|
||||
FALSE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk);
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
case DW_FORM_block1:
|
||||
@ -1191,8 +1198,7 @@ read_attribute_value (struct attribute * attr,
|
||||
return NULL;
|
||||
blk->size = read_1_byte (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 1;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk);
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
case DW_FORM_data1:
|
||||
|
Loading…
Reference in New Issue
Block a user