Ensure data pointer kept within bounds
* dwarf.c (process_extended_line_op): Don't bump data pointer past end when strnlen doesn't find string terminator. (decode_location_expression): Remove dead code. (skip_attr_bytes): Remove const from end param. Ensure data pointer doesn't pass end. (get_type_signedness): Remove const from end param. (read_and_display_attr_value): Ensure data pointer doesn't pass end. (display_debug_lines_raw, display_debug_lines_decoded): Likewise. (display_debug_pubnames_worker): Likewise. (display_debug_pubnames_worker): Use SAFE_BYTE_GET_AND INC rather than blindly incrementing data pointer. (display_debug_addr, display_debug_str_offsets): Likewise. Don't compare pointers, compare lengths.
This commit is contained in:
parent
6d1ad6f783
commit
a7077ce760
2 changed files with 72 additions and 40 deletions
|
@ -1,3 +1,19 @@
|
|||
2021-05-12 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* dwarf.c (process_extended_line_op): Don't bump data pointer past
|
||||
end when strnlen doesn't find string terminator.
|
||||
(decode_location_expression): Remove dead code.
|
||||
(skip_attr_bytes): Remove const from end param. Ensure data
|
||||
pointer doesn't pass end.
|
||||
(get_type_signedness): Remove const from end param.
|
||||
(read_and_display_attr_value): Ensure data pointer doesn't pass end.
|
||||
(display_debug_lines_raw, display_debug_lines_decoded): Likewise.
|
||||
(display_debug_pubnames_worker): Likewise.
|
||||
(display_debug_pubnames_worker): Use SAFE_BYTE_GET_AND INC rather
|
||||
than blindly incrementing data pointer.
|
||||
(display_debug_addr, display_debug_str_offsets): Likewise. Don't
|
||||
compare pointers, compare lengths.
|
||||
|
||||
2021-05-12 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* dwarf.c (SAFE_BYTE_GET_INTERNAL): Define.
|
||||
|
|
|
@ -508,7 +508,9 @@ process_extended_line_op (unsigned char * data,
|
|||
|
||||
name = data;
|
||||
l = strnlen ((char *) data, end - data);
|
||||
data += l + 1;
|
||||
data += l;
|
||||
if (data < end)
|
||||
data++;
|
||||
READ_ULEB (val, data, end);
|
||||
printf ("%s\t", dwarf_vmatoa ("u", val));
|
||||
READ_ULEB (val, data, end);
|
||||
|
@ -1612,8 +1614,6 @@ decode_location_expression (unsigned char * data,
|
|||
need_frame_base = 1;
|
||||
putchar (')');
|
||||
data += uvalue;
|
||||
if (data > end)
|
||||
data = end;
|
||||
break;
|
||||
case DW_OP_const_type:
|
||||
case DW_OP_GNU_const_type:
|
||||
|
@ -1913,16 +1913,17 @@ check_uvalue (const unsigned char * start,
|
|||
}
|
||||
|
||||
static unsigned char *
|
||||
skip_attr_bytes (unsigned long form,
|
||||
unsigned char * data,
|
||||
unsigned const char * end,
|
||||
dwarf_vma pointer_size,
|
||||
dwarf_vma offset_size,
|
||||
int dwarf_version,
|
||||
dwarf_vma * value_return)
|
||||
skip_attr_bytes (unsigned long form,
|
||||
unsigned char *data,
|
||||
unsigned char *end,
|
||||
dwarf_vma pointer_size,
|
||||
dwarf_vma offset_size,
|
||||
int dwarf_version,
|
||||
dwarf_vma *value_return)
|
||||
{
|
||||
dwarf_signed_vma svalue;
|
||||
dwarf_vma uvalue = 0;
|
||||
dwarf_vma inc = 0;
|
||||
|
||||
* value_return = 0;
|
||||
|
||||
|
@ -2000,51 +2001,54 @@ skip_attr_bytes (unsigned long form,
|
|||
|
||||
case DW_FORM_data8:
|
||||
case DW_FORM_ref_sig8:
|
||||
data += 8;
|
||||
inc = 8;
|
||||
break;
|
||||
|
||||
case DW_FORM_data16:
|
||||
data += 16;
|
||||
inc = 16;
|
||||
break;
|
||||
|
||||
case DW_FORM_string:
|
||||
data += strnlen ((char *) data, end - data) + 1;
|
||||
inc = strnlen ((char *) data, end - data) + 1;
|
||||
break;
|
||||
|
||||
case DW_FORM_block:
|
||||
case DW_FORM_exprloc:
|
||||
READ_ULEB (uvalue, data, end);
|
||||
data += uvalue;
|
||||
inc = uvalue;
|
||||
break;
|
||||
|
||||
case DW_FORM_block1:
|
||||
SAFE_BYTE_GET (uvalue, data, 1, end);
|
||||
data += 1 + uvalue;
|
||||
SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
|
||||
inc = uvalue;
|
||||
break;
|
||||
|
||||
case DW_FORM_block2:
|
||||
SAFE_BYTE_GET (uvalue, data, 2, end);
|
||||
data += 2 + uvalue;
|
||||
SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
|
||||
inc = uvalue;
|
||||
break;
|
||||
|
||||
case DW_FORM_block4:
|
||||
SAFE_BYTE_GET (uvalue, data, 4, end);
|
||||
data += 4 + uvalue;
|
||||
SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
|
||||
inc = uvalue;
|
||||
break;
|
||||
|
||||
case DW_FORM_indirect:
|
||||
READ_ULEB (form, data, end);
|
||||
if (form == DW_FORM_implicit_const)
|
||||
SKIP_ULEB (data, end);
|
||||
return skip_attr_bytes (form, data, end, pointer_size, offset_size, dwarf_version, value_return);
|
||||
return skip_attr_bytes (form, data, end, pointer_size, offset_size,
|
||||
dwarf_version, value_return);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
* value_return = uvalue;
|
||||
if (data > end)
|
||||
data = (unsigned char *) end;
|
||||
if (inc <= (dwarf_vma) (end - data))
|
||||
data += inc;
|
||||
else
|
||||
data = end;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -2159,7 +2163,7 @@ static void
|
|||
get_type_signedness (abbrev_entry *entry,
|
||||
const struct dwarf_section *section,
|
||||
unsigned char *data,
|
||||
unsigned const char *end,
|
||||
unsigned char *end,
|
||||
dwarf_vma cu_offset,
|
||||
dwarf_vma pointer_size,
|
||||
dwarf_vma offset_size,
|
||||
|
@ -2578,7 +2582,9 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_string:
|
||||
if (!do_loc)
|
||||
printf ("%c%.*s", delimiter, (int) (end - data), data);
|
||||
data += strnlen ((char *) data, end - data) + 1;
|
||||
data += strnlen ((char *) data, end - data);
|
||||
if (data < end)
|
||||
data++;
|
||||
break;
|
||||
|
||||
case DW_FORM_block:
|
||||
|
@ -4493,7 +4499,9 @@ display_debug_lines_raw (struct dwarf_section * section,
|
|||
{
|
||||
printf (" %d\t%.*s\n", ++last_dir_entry, (int) (end - data), data);
|
||||
|
||||
data += strnlen ((char *) data, end - data) + 1;
|
||||
data += strnlen ((char *) data, end - data);
|
||||
if (data < end)
|
||||
data++;
|
||||
}
|
||||
|
||||
/* PR 17512: file: 002-132094-0.004. */
|
||||
|
@ -4502,10 +4510,11 @@ display_debug_lines_raw (struct dwarf_section * section,
|
|||
}
|
||||
|
||||
/* Skip the NUL at the end of the table. */
|
||||
data++;
|
||||
if (data < end)
|
||||
data++;
|
||||
|
||||
/* Display the contents of the File Name table. */
|
||||
if (*data == 0)
|
||||
if (data >= end || *data == 0)
|
||||
printf (_("\n The File Name Table is empty.\n"));
|
||||
else
|
||||
{
|
||||
|
@ -4520,7 +4529,9 @@ display_debug_lines_raw (struct dwarf_section * section,
|
|||
|
||||
printf (" %d\t", ++state_machine_regs.last_file_entry);
|
||||
name = data;
|
||||
data += strnlen ((char *) data, end - data) + 1;
|
||||
data += strnlen ((char *) data, end - data);
|
||||
if (data < end)
|
||||
data++;
|
||||
|
||||
READ_ULEB (val, data, end);
|
||||
printf ("%s\t", dwarf_vmatoa ("u", val));
|
||||
|
@ -4539,7 +4550,8 @@ display_debug_lines_raw (struct dwarf_section * section,
|
|||
}
|
||||
|
||||
/* Skip the NUL at the end of the table. */
|
||||
data++;
|
||||
if (data < end)
|
||||
data++;
|
||||
}
|
||||
|
||||
putchar ('\n');
|
||||
|
@ -5039,7 +5051,9 @@ display_debug_lines_decoded (struct dwarf_section * section,
|
|||
|
||||
while (data < end && *data != 0)
|
||||
{
|
||||
data += strnlen ((char *) data, end - data) + 1;
|
||||
data += strnlen ((char *) data, end - data);
|
||||
if (data < end)
|
||||
data++;
|
||||
n_directories++;
|
||||
}
|
||||
|
||||
|
@ -5076,7 +5090,9 @@ display_debug_lines_decoded (struct dwarf_section * section,
|
|||
{
|
||||
/* Skip Name, directory index, last modification
|
||||
time and length of file. */
|
||||
data += strnlen ((char *) data, end - data) + 1;
|
||||
data += strnlen ((char *) data, end - data);
|
||||
if (data < end)
|
||||
data++;
|
||||
SKIP_ULEB (data, end);
|
||||
SKIP_ULEB (data, end);
|
||||
SKIP_ULEB (data, end);
|
||||
|
@ -5704,12 +5720,11 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
|||
bfd_size_type maxprint;
|
||||
dwarf_vma offset;
|
||||
|
||||
SAFE_BYTE_GET (offset, data, offset_size, end);
|
||||
SAFE_BYTE_GET_AND_INC (offset, data, offset_size, end);
|
||||
|
||||
if (offset == 0)
|
||||
break;
|
||||
|
||||
data += offset_size;
|
||||
if (data >= end)
|
||||
break;
|
||||
maxprint = (end - data) - 1;
|
||||
|
@ -5721,8 +5736,7 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
|||
const char *kind_name;
|
||||
int is_static;
|
||||
|
||||
SAFE_BYTE_GET (kind_data, data, 1, end);
|
||||
data++;
|
||||
SAFE_BYTE_GET_AND_INC (kind_data, data, 1, end);
|
||||
maxprint --;
|
||||
/* GCC computes the kind as the upper byte in the CU index
|
||||
word, and then right shifts it by the CU index size.
|
||||
|
@ -5740,7 +5754,9 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
|||
printf (" %-6lx\t%.*s\n",
|
||||
(unsigned long) offset, (int) maxprint, data);
|
||||
|
||||
data += strnlen ((char *) data, maxprint) + 1;
|
||||
data += strnlen ((char *) data, maxprint);
|
||||
if (data < end)
|
||||
data++;
|
||||
if (data >= end)
|
||||
break;
|
||||
}
|
||||
|
@ -7382,7 +7398,7 @@ display_debug_addr (struct dwarf_section *section,
|
|||
|
||||
SAFE_BYTE_GET_AND_INC (length, curr_header, 4, entry);
|
||||
if (length == 0xffffffff)
|
||||
SAFE_BYTE_GET (length, curr_header, 8, entry);
|
||||
SAFE_BYTE_GET_AND_INC (length, curr_header, 8, entry);
|
||||
end = curr_header + length;
|
||||
|
||||
SAFE_BYTE_GET_AND_INC (version, curr_header, 2, entry);
|
||||
|
@ -7451,7 +7467,7 @@ display_debug_str_offsets (struct dwarf_section *section,
|
|||
/* FIXME: We assume that this means 64-bit DWARF is being used. */
|
||||
if (length == 0xffffffff)
|
||||
{
|
||||
SAFE_BYTE_GET (length, curr, 8, end);
|
||||
SAFE_BYTE_GET_AND_INC (length, curr, 8, end);
|
||||
entry_length = 8;
|
||||
}
|
||||
else
|
||||
|
@ -7493,7 +7509,7 @@ display_debug_str_offsets (struct dwarf_section *section,
|
|||
dwarf_vma offset;
|
||||
const unsigned char * string;
|
||||
|
||||
if (curr + entry_length > entries_end)
|
||||
if ((dwarf_vma) (entries_end - curr) < entry_length)
|
||||
/* Not enough space to read one entry_length, give up. */
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue