mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-25 08:47:28 +00:00
More fixes for invalid memory accesses triggered by corrupt binaries.
PR binutils/17512 * dwarf.c (get_encoded_value): Add an 'end' parameter. Change the 'data' parameter to a double pointer and return the updated value. (decode_location_expression): Update call to get_encoded_value. (frame_need_space): Handle the case where one or both of the mallocs fails. (read_cie): Initialise the cie pointer, even if the read fails. (display_debug_frames): Warn if the calculated block_end is before the start of the block. Break the loop if the CIE could not be read. Update call to get_encoded_value. Warn if the read CFA expressions are too big. * ieee.c (ieee_archive_p) Skip processing if no bytes are read at all. (ieee_object_p): Likewise.
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
2014-11-14 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/17512
|
||||||
|
* ieee.c (ieee_archive_p) Skip processing if no bytes are read at
|
||||||
|
all.
|
||||||
|
(ieee_object_p): Likewise.
|
||||||
|
|
||||||
2014-11-13 H.J. Lu <hongjiu.lu@intel.com>
|
2014-11-13 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* coffcode.h (coff_slurp_line_table): Add cast to unsigned int.
|
* coffcode.h (coff_slurp_line_table): Add cast to unsigned int.
|
||||||
|
|||||||
@@ -1312,7 +1312,8 @@ ieee_archive_p (bfd *abfd)
|
|||||||
|
|
||||||
/* Ignore the return value here. It doesn't matter if we don't read
|
/* Ignore the return value here. It doesn't matter if we don't read
|
||||||
the entire buffer. We might have a very small ieee file. */
|
the entire buffer. We might have a very small ieee file. */
|
||||||
bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
|
if (bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd) <= 0)
|
||||||
|
goto got_wrong_format_error;
|
||||||
|
|
||||||
ieee->h.first_byte = buffer;
|
ieee->h.first_byte = buffer;
|
||||||
ieee->h.input_p = buffer;
|
ieee->h.input_p = buffer;
|
||||||
@@ -1801,7 +1802,8 @@ ieee_object_p (bfd *abfd)
|
|||||||
goto fail;
|
goto fail;
|
||||||
/* Read the first few bytes in to see if it makes sense. Ignore
|
/* Read the first few bytes in to see if it makes sense. Ignore
|
||||||
bfd_bread return value; The file might be very small. */
|
bfd_bread return value; The file might be very small. */
|
||||||
bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
|
if (bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd) <= 0)
|
||||||
|
goto got_wrong_format;
|
||||||
|
|
||||||
ieee->h.input_p = buffer;
|
ieee->h.input_p = buffer;
|
||||||
if (this_byte_and_next (&(ieee->h)) != Module_Beginning)
|
if (this_byte_and_next (&(ieee->h)) != Module_Beginning)
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
|
2014-11-14 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/17512
|
||||||
|
* dwarf.c (get_encoded_value): Add an 'end' parameter. Change the
|
||||||
|
'data' parameter to a double pointer and return the updated value.
|
||||||
|
(decode_location_expression): Update call to get_encoded_value.
|
||||||
|
(frame_need_space): Handle the case where one or both of the
|
||||||
|
mallocs fails.
|
||||||
|
(read_cie): Initialise the cie pointer, even if the read fails.
|
||||||
|
(display_debug_frames): Warn if the calculated block_end is before
|
||||||
|
the start of the block. Break the loop if the CIE could not be
|
||||||
|
read. Update call to get_encoded_value. Warn if the read CFA
|
||||||
|
expressions are too big.
|
||||||
|
|
||||||
2014-11-13 Nick Clifton <nickc@redhat.com>
|
2014-11-13 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR binutils/17531
|
PR binutils/17531
|
||||||
|
|||||||
@@ -118,13 +118,22 @@ size_of_encoded_value (int encoding)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static dwarf_vma
|
static dwarf_vma
|
||||||
get_encoded_value (unsigned char *data,
|
get_encoded_value (unsigned char **pdata,
|
||||||
int encoding,
|
int encoding,
|
||||||
struct dwarf_section *section)
|
struct dwarf_section *section,
|
||||||
|
unsigned char * end)
|
||||||
{
|
{
|
||||||
|
unsigned char * data = * pdata;
|
||||||
int size = size_of_encoded_value (encoding);
|
int size = size_of_encoded_value (encoding);
|
||||||
dwarf_vma val;
|
dwarf_vma val;
|
||||||
|
|
||||||
|
if (data + size >= end)
|
||||||
|
{
|
||||||
|
warn (_("Encoded value extends past end of section\n"));
|
||||||
|
* pdata = end;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (encoding & DW_EH_PE_signed)
|
if (encoding & DW_EH_PE_signed)
|
||||||
val = byte_get_signed (data, size);
|
val = byte_get_signed (data, size);
|
||||||
else
|
else
|
||||||
@@ -132,6 +141,8 @@ get_encoded_value (unsigned char *data,
|
|||||||
|
|
||||||
if ((encoding & 0x70) == DW_EH_PE_pcrel)
|
if ((encoding & 0x70) == DW_EH_PE_pcrel)
|
||||||
val += section->address + (data - section->start);
|
val += section->address + (data - section->start);
|
||||||
|
|
||||||
|
* pdata = data + size;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1238,8 +1249,7 @@ decode_location_expression (unsigned char * data,
|
|||||||
dwarf_vma addr;
|
dwarf_vma addr;
|
||||||
|
|
||||||
encoding = *data++;
|
encoding = *data++;
|
||||||
addr = get_encoded_value (data, encoding, section);
|
addr = get_encoded_value (&data, encoding, section, end);
|
||||||
data += size_of_encoded_value (encoding);
|
|
||||||
|
|
||||||
printf ("DW_OP_GNU_encoded_addr: fmt:%02x addr:", encoding);
|
printf ("DW_OP_GNU_encoded_addr: fmt:%02x addr:", encoding);
|
||||||
print_dwarf_vma (addr, pointer_size);
|
print_dwarf_vma (addr, pointer_size);
|
||||||
@@ -5068,6 +5078,14 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
|
|||||||
fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
|
fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
|
||||||
sizeof (short int));
|
sizeof (short int));
|
||||||
fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
|
fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
|
||||||
|
/* PR 17512: file:002-10025-0.005. */
|
||||||
|
if (fc->col_type == NULL || fc->col_offset == NULL)
|
||||||
|
{
|
||||||
|
error (_("Out of memory allocating %u columns in dwarf frame arrays\n"),
|
||||||
|
fc->ncols);
|
||||||
|
fc->ncols = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (prev < fc->ncols)
|
while (prev < fc->ncols)
|
||||||
{
|
{
|
||||||
@@ -5302,6 +5320,7 @@ read_cie (unsigned char *start, unsigned char *end,
|
|||||||
unsigned char *augmentation_data = NULL;
|
unsigned char *augmentation_data = NULL;
|
||||||
unsigned long augmentation_data_len = 0;
|
unsigned long augmentation_data_len = 0;
|
||||||
|
|
||||||
|
* p_cie = NULL;
|
||||||
/* PR 17512: file: 001-228113-0.004. */
|
/* PR 17512: file: 001-228113-0.004. */
|
||||||
if (start >= end)
|
if (start >= end)
|
||||||
return end;
|
return end;
|
||||||
@@ -5427,6 +5446,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
saved_start = start;
|
saved_start = start;
|
||||||
|
|
||||||
SAFE_BYTE_GET_AND_INC (length, start, 4, end);
|
SAFE_BYTE_GET_AND_INC (length, start, 4, end);
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
{
|
{
|
||||||
printf ("\n%08lx ZERO terminator\n\n",
|
printf ("\n%08lx ZERO terminator\n\n",
|
||||||
@@ -5447,7 +5467,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
}
|
}
|
||||||
|
|
||||||
block_end = saved_start + length + initial_length_size;
|
block_end = saved_start + length + initial_length_size;
|
||||||
if (block_end > end)
|
if (block_end > end || block_end < start)
|
||||||
{
|
{
|
||||||
warn ("Invalid length 0x%s in FDE at %#08lx\n",
|
warn ("Invalid length 0x%s in FDE at %#08lx\n",
|
||||||
dwarf_vmatoa_1 (NULL, length, offset_size),
|
dwarf_vmatoa_1 (NULL, length, offset_size),
|
||||||
@@ -5465,6 +5485,9 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
|
|
||||||
start = read_cie (start, end, &cie, &version,
|
start = read_cie (start, end, &cie, &version,
|
||||||
&augmentation_data_len, &augmentation_data);
|
&augmentation_data_len, &augmentation_data);
|
||||||
|
/* PR 17512: file: 027-135133-0.005. */
|
||||||
|
if (cie == NULL)
|
||||||
|
break;
|
||||||
fc = cie;
|
fc = cie;
|
||||||
fc->next = chunks;
|
fc->next = chunks;
|
||||||
chunks = fc;
|
chunks = fc;
|
||||||
@@ -5621,11 +5644,9 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
|
|
||||||
segment_selector = 0;
|
segment_selector = 0;
|
||||||
if (fc->segment_size)
|
if (fc->segment_size)
|
||||||
{
|
SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
|
||||||
SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
|
|
||||||
}
|
fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section, end);
|
||||||
fc->pc_begin = get_encoded_value (start, fc->fde_encoding, section);
|
|
||||||
start += encoded_ptr_size;
|
|
||||||
|
|
||||||
/* FIXME: It appears that sometimes the final pc_range value is
|
/* FIXME: It appears that sometimes the final pc_range value is
|
||||||
encoded in less than encoded_ptr_size bytes. See the x86_64
|
encoded in less than encoded_ptr_size bytes. See the x86_64
|
||||||
@@ -5680,8 +5701,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
|
|
||||||
while (start < block_end)
|
while (start < block_end)
|
||||||
{
|
{
|
||||||
unsigned op, opa;
|
unsigned int reg, op, opa;
|
||||||
unsigned long reg, temp;
|
unsigned long temp;
|
||||||
|
|
||||||
op = *start++;
|
op = *start++;
|
||||||
opa = op & 0x3f;
|
opa = op & 0x3f;
|
||||||
@@ -5753,13 +5774,26 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
break;
|
break;
|
||||||
case DW_CFA_def_cfa_expression:
|
case DW_CFA_def_cfa_expression:
|
||||||
temp = LEB ();
|
temp = LEB ();
|
||||||
start += temp;
|
if (start + temp < start)
|
||||||
|
{
|
||||||
|
warn (_("Corrupt CFA_def expression value: %lu\n"), temp);
|
||||||
|
start = block_end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
start += temp;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_expression:
|
case DW_CFA_expression:
|
||||||
case DW_CFA_val_expression:
|
case DW_CFA_val_expression:
|
||||||
reg = LEB ();
|
reg = LEB ();
|
||||||
temp = LEB ();
|
temp = LEB ();
|
||||||
start += temp;
|
if (start + temp < start)
|
||||||
|
{
|
||||||
|
/* PR 17512: file:306-192417-0.005. */
|
||||||
|
warn (_("Corrupt CFA expression value: %lu\n"), temp);
|
||||||
|
start = block_end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
start += temp;
|
||||||
if (frame_need_space (fc, reg) >= 0)
|
if (frame_need_space (fc, reg) >= 0)
|
||||||
fc->col_type[reg] = DW_CFA_undefined;
|
fc->col_type[reg] = DW_CFA_undefined;
|
||||||
break;
|
break;
|
||||||
@@ -5859,8 +5893,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_set_loc:
|
case DW_CFA_set_loc:
|
||||||
vma = get_encoded_value (start, fc->fde_encoding, section);
|
vma = get_encoded_value (&start, fc->fde_encoding, section, end);
|
||||||
start += encoded_ptr_size;
|
|
||||||
if (do_debug_frames_interp)
|
if (do_debug_frames_interp)
|
||||||
frame_display_row (fc, &need_col_headers, &max_regs);
|
frame_display_row (fc, &need_col_headers, &max_regs);
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user