aboutsummaryrefslogtreecommitdiff
path: root/binutils/dwarf.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-05-12 17:27:34 +0930
committerAlan Modra <amodra@gmail.com>2021-05-12 21:29:25 +0930
commita7077ce7604f78b896595dceccd89d70d2a050a0 (patch)
tree4877e8c13d3876a002a26fd6911793fa0c44ddc9 /binutils/dwarf.c
parent6d1ad6f7834d62bedec138aaf3ac872c60702ecd (diff)
downloadgdb-a7077ce7604f78b896595dceccd89d70d2a050a0.zip
gdb-a7077ce7604f78b896595dceccd89d70d2a050a0.tar.gz
gdb-a7077ce7604f78b896595dceccd89d70d2a050a0.tar.bz2
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.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r--binutils/dwarf.c96
1 files changed, 56 insertions, 40 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index e297a3d..56983e1 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -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;