#define CHAR_BIT 8
#endif
+#ifndef ENABLE_CHECKING
+#define ENABLE_CHECKING 0
+#endif
+
#undef MAX
#undef MIN
#define MAX(a, b) ((a) > (b) ? (a) : (b))
unsigned int size = size_of_encoded_value (encoding);
dwarf_vma val;
- if (data + size >= end)
+ if (data >= end || size > (size_t) (end - data))
{
warn (_("Encoded value extends past end of section\n"));
* pdata = end;
printf ("%*s", len + 1, "");
}
-/* Format a 64-bit value, given as two 32-bit values, in hex.
- For reentrancy, this uses a buffer provided by the caller. */
-
-static const char *
-dwarf_vmatoa64 (dwarf_vma hvalue, dwarf_vma lvalue, char *buf,
- unsigned int buf_len)
-{
- int len = 0;
-
- if (hvalue == 0)
- snprintf (buf, buf_len, "%" DWARF_VMA_FMT "x", lvalue);
- else
- {
- len = snprintf (buf, buf_len, "%" DWARF_VMA_FMT "x", hvalue);
- snprintf (buf + len, buf_len - len,
- "%08" DWARF_VMA_FMT "x", lvalue);
- }
-
- return buf;
-}
-
/* Read in a LEB128 encoded value starting at address DATA.
If SIGN is true, return a signed LEB128 value.
If LENGTH_RETURN is not NULL, return in it the number of bytes read.
return result;
}
-/* Read AMOUNT bytes from PTR and store them in VAL as an unsigned value.
- Checks to make sure that the read will not reach or pass END
- and that VAL is big enough to hold AMOUNT bytes. */
-#define SAFE_BYTE_GET(VAL, PTR, AMOUNT, END) \
- do \
- { \
- unsigned int amount = (AMOUNT); \
- if (sizeof (VAL) < amount) \
- { \
+/* Read AMOUNT bytes from PTR and store them in VAL.
+ Checks to make sure that the read will not reach or pass END.
+ FUNC chooses whether the value read is unsigned or signed, and may
+ be either byte_get or byte_get_signed. If INC is true, PTR is
+ incremented after reading the value.
+ This macro cannot protect against PTR values derived from user input.
+ The C standard sections 6.5.6 and 6.5.8 say attempts to do so using
+ pointers is undefined behaviour. */
+#define SAFE_BYTE_GET_INTERNAL(VAL, PTR, AMOUNT, END, FUNC, INC) \
+ do \
+ { \
+ size_t amount = (AMOUNT); \
+ if (sizeof (VAL) < amount) \
+ { \
error (ngettext ("internal error: attempt to read %d byte " \
"of data in to %d sized variable", \
"internal error: attempt to read %d bytes " \
"of data in to %d sized variable", \
amount), \
- amount, (int) sizeof (VAL)); \
- amount = sizeof (VAL); \
- } \
- if (((PTR) + amount) >= (END)) \
- { \
- if ((PTR) < (END)) \
- amount = (END) - (PTR); \
- else \
- amount = 0; \
- } \
- if (amount == 0 || amount > 8) \
- VAL = 0; \
- else \
- VAL = byte_get ((PTR), amount); \
- } \
+ (int) amount, (int) sizeof (VAL)); \
+ amount = sizeof (VAL); \
+ } \
+ if (ENABLE_CHECKING) \
+ assert ((PTR) <= (END)); \
+ size_t avail = (END) - (PTR); \
+ if ((PTR) > (END)) \
+ avail = 0; \
+ if (amount > avail) \
+ amount = avail; \
+ if (amount == 0) \
+ (VAL) = 0; \
+ else \
+ (VAL) = (FUNC) ((PTR), amount); \
+ if (INC) \
+ (PTR) += amount; \
+ } \
while (0)
-/* Like SAFE_BYTE_GET, but also increments PTR by AMOUNT. */
+#define SAFE_BYTE_GET(VAL, PTR, AMOUNT, END) \
+ SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get, false)
+
#define SAFE_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END) \
- do \
- { \
- SAFE_BYTE_GET (VAL, PTR, AMOUNT, END); \
- PTR += AMOUNT; \
- } \
- while (0)
+ SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get, true)
-/* Like SAFE_BYTE_GET, but reads a signed value. */
#define SAFE_SIGNED_BYTE_GET(VAL, PTR, AMOUNT, END) \
- do \
- { \
- unsigned int amount = (AMOUNT); \
- if (((PTR) + amount) >= (END)) \
- { \
- if ((PTR) < (END)) \
- amount = (END) - (PTR); \
- else \
- amount = 0; \
- } \
- if (amount) \
- VAL = byte_get_signed ((PTR), amount); \
- else \
- VAL = 0; \
- } \
- while (0)
+ SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get_signed, false)
-/* Like SAFE_SIGNED_BYTE_GET, but also increments PTR by AMOUNT. */
#define SAFE_SIGNED_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END) \
- do \
- { \
- SAFE_SIGNED_BYTE_GET (VAL, PTR, AMOUNT, END); \
- PTR += AMOUNT; \
- } \
- while (0)
-
-#define SAFE_BYTE_GET64(PTR, HIGH, LOW, END) \
- do \
- { \
- if (((PTR) + 8) <= (END)) \
- { \
- byte_get_64 ((PTR), (HIGH), (LOW)); \
- } \
- else \
- { \
- * (LOW) = * (HIGH) = 0; \
- } \
- } \
- while (0)
+ SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get_signed, true)
typedef struct State_Machine_Registers
{
READ_ULEB (len, data, end);
header_len = data - orig_data;
- if (len == 0 || data == end || len > (size_t) (end - data))
+ if (len == 0 || data >= end || len > (size_t) (end - data))
{
warn (_("Badly formed extended line op encountered!\n"));
return header_len;
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);
printf ("%.*s\n\n", (int) l, name);
}
- if (((size_t) (data - orig_data) != len + header_len) || data == end)
+ if (((size_t) (data - orig_data) != len + header_len) || data >= end)
warn (_("DW_LNE_define_file: Bad opcode length\n"));
break;
dwarf_vma str_offset;
const char * ret;
unsigned char *curr = index_section->start;
- const unsigned char *end = curr + index_section->size;
+ unsigned char *end = curr + index_section->size;
dwarf_vma length;
if (index_section->start == NULL)
{
/* Skip the version and padding bytes.
We assume that they are correct. */
- curr += 4;
+ if (end - curr >= 4)
+ curr += 4;
+ else
+ curr = end;
+ if (length >= 4)
+ length -= 4;
+ else
+ length = 0;
+
+ if (this_set != NULL
+ && this_set->section_sizes[DW_SECT_STR_OFFSETS] < length)
+ length = this_set->section_sizes[DW_SECT_STR_OFFSETS];
- /* FIXME: The code below assumes that there is only one table
- in the .debug_str_offsets section, so check that now. */
- if ((offset_size == 4 && curr + length < (end - 8))
- || (offset_size == 8 && curr + length < (end - 16)))
+ if (length > (dwarf_vma) (end - curr))
{
- warn (_("index table size is too small %s vs %s\n"),
+ warn (_("index table size too large for section %s vs %s\n"),
dwarf_vmatoa ("x", length),
dwarf_vmatoa ("x", index_section->size));
+ length = end - curr;
+ }
+
+ if (length < offset_size)
+ {
+ warn (_("index table size %s is too small\n"),
+ dwarf_vmatoa ("x", length));
return _("<table too small>");
}
}
if (this_set != NULL)
index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
- if (index_offset >= length)
+ if (index_offset >= length
+ || length - index_offset < offset_size)
{
warn (_("DW_FORM_GNU_str_index offset too big: 0x%s vs 0x%s\n"),
dwarf_vmatoa ("x", index_offset),
{
unsigned long attribute;
unsigned long form;
- bfd_signed_vma implicit_const;
+ dwarf_signed_vma implicit_const;
struct abbrev_attr * next;
}
abbrev_attr;
}
static void
-add_abbrev_attr (unsigned long attribute,
- unsigned long form,
- bfd_signed_vma implicit_const,
- abbrev_list * list)
+add_abbrev_attr (unsigned long attribute,
+ unsigned long form,
+ dwarf_signed_vma implicit_const,
+ abbrev_list * list)
{
abbrev_attr *attr;
attr = (abbrev_attr *) xmalloc (sizeof (*attr));
- attr->attribute = attribute;
- attr->form = form;
+ attr->attribute = attribute;
+ attr->form = form;
attr->implicit_const = implicit_const;
- attr->next = NULL;
+ attr->next = NULL;
assert (list != NULL && list->last_abbrev != NULL);
an abbreviation set was found. */
static unsigned char *
-process_abbrev_set (unsigned char * start,
- const unsigned char * end,
- abbrev_list * list)
+process_abbrev_set (struct dwarf_section *section,
+ dwarf_vma abbrev_base,
+ dwarf_vma abbrev_size,
+ dwarf_vma abbrev_offset,
+ abbrev_list *list)
{
+ if (abbrev_base >= section->size
+ || abbrev_size > section->size - abbrev_base)
+ {
+ /* PR 17531: file:4bcd9ce9. */
+ warn (_("Debug info is corrupted, abbrev size (%lx) is larger than "
+ "abbrev section size (%lx)\n"),
+ (unsigned long) (abbrev_base + abbrev_size),
+ (unsigned long) section->size);
+ return NULL;
+ }
+ if (abbrev_offset >= abbrev_size)
+ {
+ warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than "
+ "abbrev section size (%lx)\n"),
+ (unsigned long) abbrev_offset,
+ (unsigned long) abbrev_size);
+ return NULL;
+ }
+
+ unsigned char *start = section->start + abbrev_base;
+ unsigned char *end = start + abbrev_size;
+ start += abbrev_offset;
while (start < end)
{
unsigned long entry;
{
unsigned long form;
/* Initialize it due to a false compiler warning. */
- bfd_signed_vma implicit_const = -1;
+ dwarf_signed_vma implicit_const = -1;
READ_ULEB (attribute, start, end);
if (start == end)
need_frame_base = 1;
putchar (')');
data += uvalue;
- if (data > end)
- data = end;
break;
case DW_OP_const_type:
case DW_OP_GNU_const_type:
return NULL;
}
-/* Add INC to HIGH_BITS:LOW_BITS. */
-static void
-add64 (dwarf_vma * high_bits, dwarf_vma * low_bits, dwarf_vma inc)
-{
- dwarf_vma tmp = * low_bits;
-
- tmp += inc;
-
- /* FIXME: There is probably a better way of handling this:
-
- We need to cope with dwarf_vma being a 32-bit or 64-bit
- type. Plus regardless of its size LOW_BITS is meant to
- only hold 32-bits, so if there is overflow or wrap around
- we must propagate into HIGH_BITS. */
- if (tmp < * low_bits)
- {
- ++ * high_bits;
- }
- else if (sizeof (tmp) > 8
- && (tmp >> 31) > 1)
- {
- ++ * high_bits;
- tmp &= 0xFFFFFFFF;
- }
-
- * low_bits = tmp;
-}
-
static const char *
fetch_alt_indirect_string (dwarf_vma offset)
{
}
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;
break;
case DW_FORM_ref8:
- {
- dwarf_vma high_bits;
-
- SAFE_BYTE_GET64 (data, &high_bits, &uvalue, end);
- data += 8;
- if (sizeof (uvalue) > 4)
- uvalue += high_bits << 32;
- else if (high_bits != 0)
- {
- /* FIXME: What to do ? */
- return NULL;
- }
- break;
- }
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 8, end);
+ break;
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;
}
associated with it. */
static abbrev_entry *
-get_type_abbrev_from_form (unsigned long form,
- unsigned long uvalue,
- dwarf_vma cu_offset,
- const struct dwarf_section * section,
- unsigned long * abbrev_num_return,
- unsigned char ** data_return,
- unsigned long * cu_offset_return)
+get_type_abbrev_from_form (unsigned long form,
+ unsigned long uvalue,
+ dwarf_vma cu_offset,
+ const struct dwarf_section *section,
+ unsigned long *abbrev_num_return,
+ unsigned char **data_return,
+ abbrev_map **map_return)
{
unsigned long abbrev_number;
abbrev_map * map;
return NULL;
}
- if (cu_offset_return != NULL)
+ if (map_return != NULL)
{
if (form == DW_FORM_ref_addr)
- * cu_offset_return = map->start;
+ *map_return = map;
else
- * cu_offset_return = cu_offset;
+ *map_return = NULL;
}
READ_ULEB (abbrev_number, data, section->start + section->size);
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,
case DW_AT_type:
/* Recurse. */
{
- abbrev_entry * type_abbrev;
- unsigned char * type_data;
- unsigned long type_cu_offset;
+ abbrev_entry *type_abbrev;
+ unsigned char *type_data;
+ abbrev_map *map;
type_abbrev = get_type_abbrev_from_form (attr->form,
uvalue,
cu_offset,
section,
NULL /* abbrev num return */,
- & type_data,
- & type_cu_offset);
+ &type_data,
+ &map);
if (type_abbrev == NULL)
break;
- get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+ get_type_signedness (type_abbrev, section, type_data,
+ map ? section->start + map->end : end,
+ map ? map->start : cu_offset,
pointer_size, offset_size, dwarf_version,
is_signed, nesting + 1);
}
unsigned char discriminant;
unsigned int bytes_read;
- SAFE_BYTE_GET (discriminant, data, 1, end);
+ SAFE_BYTE_GET_AND_INC (discriminant, data, 1, end);
-- uvalue;
- data ++;
assert (uvalue > 0);
switch (discriminant)
int level)
{
dwarf_signed_vma svalue;
- dwarf_vma uvalue = 0;
- unsigned char * block_start = NULL;
- unsigned char * orig_data = data;
+ dwarf_vma uvalue = 0;
+ dwarf_vma uvalue_hi = 0;
+ unsigned char *block_start = NULL;
+ unsigned char *orig_data = data;
if (data > end || (data == end && form != DW_FORM_flag_present))
{
SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
break;
+ case DW_FORM_ref_sup8:
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 8, end);
+ break;
+
+ case DW_FORM_data16:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 8, end);
+ SAFE_BYTE_GET_AND_INC (uvalue_hi, data, 8, end);
+ if (byte_get != byte_get_little_endian)
+ {
+ dwarf_vma utmp = uvalue;
+ uvalue = uvalue_hi;
+ uvalue_hi = utmp;
+ }
+ break;
+
case DW_FORM_sdata:
READ_SLEB (svalue, data, end);
uvalue = svalue;
case DW_FORM_data8:
if (!do_loc)
{
- dwarf_vma high_bits;
- dwarf_vma utmp;
- char buf[64];
-
- SAFE_BYTE_GET64 (data, &high_bits, &uvalue, end);
- utmp = uvalue;
+ dwarf_vma utmp = uvalue;
if (form == DW_FORM_ref8)
- add64 (& high_bits, & utmp, cu_offset);
- printf ("%c0x%s", delimiter,
- dwarf_vmatoa64 (high_bits, utmp, buf, sizeof (buf)));
- }
-
- if ((do_loc || do_debug_loc || do_debug_ranges)
- && num_debug_info_entries == 0)
- {
- if (sizeof (uvalue) == 8)
- SAFE_BYTE_GET (uvalue, data, 8, end);
- else
- error (_("DW_FORM_data8 is unsupported when sizeof (dwarf_vma) != 8\n"));
+ utmp += cu_offset;
+ printf ("%c0x%s", delimiter, dwarf_vmatoa ("x", utmp));
}
-
- data += 8;
break;
case DW_FORM_data16:
if (!do_loc)
- {
- dwarf_vma left_high_bits, left_low_bits;
- dwarf_vma right_high_bits, right_low_bits;
-
- SAFE_BYTE_GET64 (data, &left_high_bits, &left_low_bits, end);
- SAFE_BYTE_GET64 (data + 8, &right_high_bits, &right_low_bits, end);
- if (byte_get == byte_get_little_endian)
- {
- /* Swap them. */
- left_high_bits ^= right_high_bits;
- right_high_bits ^= left_high_bits;
- left_high_bits ^= right_high_bits;
- left_low_bits ^= right_low_bits;
- right_low_bits ^= left_low_bits;
- left_low_bits ^= right_low_bits;
- }
- printf (" 0x%08" DWARF_VMA_FMT "x%08" DWARF_VMA_FMT "x"
- "%08" DWARF_VMA_FMT "x%08" DWARF_VMA_FMT "x",
- left_high_bits, left_low_bits, right_high_bits,
- right_low_bits);
- }
- data += 16;
+ printf (" 0x%s%s",
+ uvalue_hi == 0 ? "" : dwarf_vmatoa ("x", uvalue_hi),
+ dwarf_vmatoa_1 ("x", uvalue, uvalue_hi == 0 ? 0 : 8));
break;
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:
case DW_FORM_ref_sig8:
if (!do_loc)
- {
- dwarf_vma high_bits;
- char buf[64];
-
- SAFE_BYTE_GET64 (data, &high_bits, &uvalue, end);
- if (do_wide)
- /* We have already displayed the form name. */
- printf ("%c: 0x%s", delimiter,
- dwarf_vmatoa64 (high_bits, uvalue, buf, sizeof (buf)));
- else
- printf ("%csignature: 0x%s", delimiter,
- dwarf_vmatoa64 (high_bits, uvalue, buf, sizeof (buf)));
- }
- data += 8;
+ printf ("%c%s: 0x%s", delimiter, do_wide ? "" : "signature",
+ dwarf_vmatoa ("x", uvalue));
break;
case DW_FORM_GNU_addr_index:
bool is_signed = false;
abbrev_entry *type_abbrev;
unsigned char *type_data;
- unsigned long type_cu_offset;
+ abbrev_map *map;
type_abbrev = get_type_abbrev_from_form (form, uvalue, cu_offset,
- section, NULL, & type_data, & type_cu_offset);
+ section, NULL, &type_data, &map);
if (type_abbrev != NULL)
{
- get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+ get_type_signedness (type_abbrev, section, type_data,
+ map ? section->start + map->end : end,
+ map ? map->start : cu_offset,
pointer_size, offset_size, dwarf_version,
& is_signed, 0);
}
unsigned int unit;
unsigned int num_units = 0;
- if ((do_loc || do_debug_loc || do_debug_ranges)
- && num_debug_info_entries == 0
- && ! do_types)
+ /* First scan the section to get the number of comp units.
+ Length sanity checks are done here. */
+ for (section_begin = start, num_units = 0; section_begin < end;
+ num_units ++)
{
dwarf_vma length;
- /* First scan the section to get the number of comp units. */
- for (section_begin = start, num_units = 0; section_begin < end;
- num_units ++)
- {
- /* Read the first 4 bytes. For a 32-bit DWARF section, this
- will be the length. For a 64-bit DWARF section, it'll be
- the escape code 0xffffffff followed by an 8 byte length. */
- SAFE_BYTE_GET (length, section_begin, 4, end);
-
- if (length == 0xffffffff)
- {
- SAFE_BYTE_GET (length, section_begin + 4, 8, end);
- section_begin += length + 12;
- }
- else if (length >= 0xfffffff0 && length < 0xffffffff)
- {
- warn (_("Reserved length value (0x%s) found in section %s\n"),
- dwarf_vmatoa ("x", length), section->name);
- return false;
- }
- else
- section_begin += length + 4;
+ /* Read the first 4 bytes. For a 32-bit DWARF section, this
+ will be the length. For a 64-bit DWARF section, it'll be
+ the escape code 0xffffffff followed by an 8 byte length. */
+ SAFE_BYTE_GET_AND_INC (length, section_begin, 4, end);
- /* Negative values are illegal, they may even cause infinite
- looping. This can happen if we can't accurately apply
- relocations to an object file, or if the file is corrupt. */
- if ((signed long) length <= 0 || section_begin < start)
- {
- warn (_("Corrupt unit length (0x%s) found in section %s\n"),
- dwarf_vmatoa ("x", length), section->name);
- return false;
- }
+ if (length == 0xffffffff)
+ SAFE_BYTE_GET_AND_INC (length, section_begin, 8, end);
+ else if (length >= 0xfffffff0 && length < 0xffffffff)
+ {
+ warn (_("Reserved length value (0x%s) found in section %s\n"),
+ dwarf_vmatoa ("x", length), section->name);
+ return false;
}
- if (num_units == 0)
+ /* Negative values are illegal, they may even cause infinite
+ looping. This can happen if we can't accurately apply
+ relocations to an object file, or if the file is corrupt. */
+ if (length > (size_t) (end - section_begin))
{
- error (_("No comp units in %s section ?\n"), section->name);
+ warn (_("Corrupt unit length (0x%s) found in section %s\n"),
+ dwarf_vmatoa ("x", length), section->name);
return false;
}
+ section_begin += length;
+ }
+
+ if (num_units == 0)
+ {
+ error (_("No comp units in %s section ?\n"), section->name);
+ return false;
+ }
+
+ if ((do_loc || do_debug_loc || do_debug_ranges)
+ && num_debug_info_entries == 0
+ && ! do_types)
+ {
/* Then allocate an array to hold the information. */
debug_information = (debug_info *) cmalloc (num_units,
size_t abbrev_size;
dwarf_vma cu_offset;
unsigned int offset_size;
- unsigned int initial_length_size;
struct cu_tu_set * this_set;
abbrev_list * list;
+ unsigned char *end_cu;
hdrptr = start;
+ cu_offset = start - section_begin;
SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 4, end);
{
SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 8, end);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
-
- SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end);
+ offset_size = 4;
+ end_cu = hdrptr + compunit.cu_length;
- cu_offset = start - section_begin;
+ SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu);
this_set = find_cu_tu_set_v2 (cu_offset, do_types);
}
else
{
- SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
do_types = (compunit.cu_unit_type == DW_UT_type);
- SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
}
- SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size,
+ end_cu);
if (compunit.cu_unit_type == DW_UT_split_compile
|| compunit.cu_unit_type == DW_UT_skeleton)
{
uint64_t dwo_id;
- SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end);
+ SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end_cu);
}
if (this_set == NULL)
list = new_abbrev_list (abbrev_base,
compunit.cu_abbrev_offset);
- next = process_abbrev_set
- (((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + compunit.cu_abbrev_offset),
- ((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + abbrev_size),
- list);
+ next = process_abbrev_set (&debug_displays[abbrev_sec].section,
+ abbrev_base, abbrev_size,
+ compunit.cu_abbrev_offset, list);
list->start_of_next_abbrevs = next;
}
- start = section_begin + cu_offset + compunit.cu_length
- + initial_length_size;
+ start = end_cu;
record_abbrev_list_for_cu (cu_offset, start - section_begin, list);
}
unsigned char *tags;
int level, last_level, saved_level;
dwarf_vma cu_offset;
- unsigned long sec_off;
unsigned int offset_size;
- unsigned int initial_length_size;
- dwarf_vma signature_high = 0;
- dwarf_vma signature_low = 0;
+ dwarf_vma signature = 0;
dwarf_vma type_offset = 0;
struct cu_tu_set *this_set;
dwarf_vma abbrev_base;
size_t abbrev_size;
abbrev_list * list = NULL;
+ unsigned char *end_cu;
hdrptr = start;
+ cu_offset = start - section_begin;
SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 4, end);
{
SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 8, end);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
-
- SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end);
+ offset_size = 4;
+ end_cu = hdrptr + compunit.cu_length;
- cu_offset = start - section_begin;
+ SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu);
this_set = find_cu_tu_set_v2 (cu_offset, do_types);
}
else
{
- SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
do_types = (compunit.cu_unit_type == DW_UT_type);
- SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
}
- SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end_cu);
if (this_set == NULL)
{
}
if (compunit.cu_version < 5)
- SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
bool do_dwo_id = false;
uint64_t dwo_id = 0;
if (compunit.cu_unit_type == DW_UT_split_compile
|| compunit.cu_unit_type == DW_UT_skeleton)
{
- SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end);
+ SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end_cu);
do_dwo_id = true;
}
if (do_types)
{
- SAFE_BYTE_GET64 (hdrptr, &signature_high, &signature_low, end);
- hdrptr += 8;
- SAFE_BYTE_GET_AND_INC (type_offset, hdrptr, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, end_cu);
+ SAFE_BYTE_GET_AND_INC (type_offset, hdrptr, offset_size, end_cu);
}
- if (dwarf_start_die > (cu_offset + compunit.cu_length
- + initial_length_size))
+ if (dwarf_start_die >= (size_t) (end_cu - section_begin))
{
- start = section_begin + cu_offset + compunit.cu_length
- + initial_length_size;
+ start = end_cu;
continue;
}
printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size);
if (do_types)
{
- char buf[64];
-
printf (_(" Signature: 0x%s\n"),
- dwarf_vmatoa64 (signature_high, signature_low,
- buf, sizeof (buf)));
+ dwarf_vmatoa ("x", signature));
printf (_(" Type Offset: 0x%s\n"),
dwarf_vmatoa ("x", type_offset));
}
}
}
- sec_off = cu_offset + initial_length_size;
- if (sec_off + compunit.cu_length < sec_off
- || sec_off + compunit.cu_length > section->size)
- {
- warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
- section->name,
- (unsigned long) cu_offset,
- dwarf_vmatoa ("x", compunit.cu_length));
- num_units = unit;
- break;
- }
-
tags = hdrptr;
- start += compunit.cu_length + initial_length_size;
+ start = end_cu;
if (compunit.cu_version < 2 || compunit.cu_version > 5)
{
}
/* Process the abbrevs used by this compilation unit. */
- if (compunit.cu_abbrev_offset >= abbrev_size)
- warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than abbrev section size (%lx)\n"),
- (unsigned long) compunit.cu_abbrev_offset,
- (unsigned long) abbrev_size);
- /* PR 17531: file:4bcd9ce9. */
- else if ((abbrev_base + abbrev_size)
- > debug_displays [abbrev_sec].section.size)
- warn (_("Debug info is corrupted, abbrev size (%lx) is larger than abbrev section size (%lx)\n"),
- (unsigned long) abbrev_base + abbrev_size,
- (unsigned long) debug_displays [abbrev_sec].section.size);
- else
+ list = find_abbrev_list_by_abbrev_offset (abbrev_base,
+ compunit.cu_abbrev_offset);
+ if (list == NULL)
{
- list = find_abbrev_list_by_abbrev_offset (abbrev_base,
- compunit.cu_abbrev_offset);
- if (list == NULL)
- {
- unsigned char * next;
-
- list = new_abbrev_list (abbrev_base,
- compunit.cu_abbrev_offset);
- next = process_abbrev_set
- (((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + compunit.cu_abbrev_offset),
- ((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + abbrev_size),
- list);
- list->start_of_next_abbrevs = next;
- }
+ unsigned char *next;
+
+ list = new_abbrev_list (abbrev_base,
+ compunit.cu_abbrev_offset);
+ next = process_abbrev_set (&debug_displays[abbrev_sec].section,
+ abbrev_base, abbrev_size,
+ compunit.cu_abbrev_offset, list);
+ list->start_of_next_abbrevs = next;
}
level = 0;
attr->implicit_const,
section_begin,
tags,
- end,
+ start,
cu_offset,
compunit.cu_pointer_size,
offset_size,
unsigned char ** end_of_sequence)
{
unsigned char *hdrptr;
- unsigned int initial_length_size;
/* Extract information from the Line Number Program Header.
(section 6.2.4 in the Dwarf3 doc). */
/* This section is 64-bit DWARF 3. */
SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 8, end);
linfo->li_offset_size = 8;
- initial_length_size = 12;
}
else
- {
- linfo->li_offset_size = 4;
- initial_length_size = 4;
- }
+ linfo->li_offset_size = 4;
- if (linfo->li_length + initial_length_size > section->size)
+ if (linfo->li_length > (size_t) (end - hdrptr))
{
/* If the length field has a relocation against it, then we should
not complain if it is inaccurate (and probably negative). This
is used to compute the correct length once that is done. */
if (reloc_at (section, (hdrptr - section->start) - linfo->li_offset_size))
{
- linfo->li_length = (end - data) - initial_length_size;
+ linfo->li_length = end - hdrptr;
}
else
{
return NULL;
}
}
+ end = hdrptr + linfo->li_length;
/* Get and check the version number. */
SAFE_BYTE_GET_AND_INC (linfo->li_version, hdrptr, 2, end);
SAFE_BYTE_GET_AND_INC (linfo->li_line_range, hdrptr, 1, end);
SAFE_BYTE_GET_AND_INC (linfo->li_opcode_base, hdrptr, 1, end);
- * end_of_sequence = data + linfo->li_length + initial_length_size;
- /* PR 17512: file:002-117414-0.004. */
- if (* end_of_sequence > end)
- {
- warn (_("Line length %s extends beyond end of section\n"),
- dwarf_vmatoa ("u", linfo->li_length));
- * end_of_sequence = end;
- return NULL;
- }
-
+ *end_of_sequence = end;
return hdrptr;
}
{
SKIP_ULEB (data, end);
SKIP_ULEB (data, end);
- if (data == end)
+ if (data >= end)
{
warn (_("%s: Corrupt format description entry\n"), table_name);
return data;
printf (_("\n The %s is empty.\n"), table_name);
return data;
}
- else if (data == end)
+ else if (data >= end)
{
warn (_("%s: Corrupt entry count - expected %s but none found\n"),
table_name, dwarf_vmatoa ("x", data_count));
}
}
- if (data == end && (datai < data_count - 1))
+ if (data >= end && (datai < data_count - 1))
{
warn (_("\n%s: Corrupt entries list\n"), table_name);
return data;
{
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. */
}
/* 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
{
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));
printf ("%s\t", dwarf_vmatoa ("u", val));
printf ("%.*s\n", (int)(end - name), name);
- if (data == end)
+ if (data >= end)
{
warn (_("Corrupt file name table entry\n"));
break;
}
/* Skip the NUL at the end of the table. */
- data++;
+ if (data < end)
+ data++;
}
putchar ('\n');
}
READ_ULEB (n_directories, data, end);
- if (data == end)
+ if (data >= end)
{
warn (_("Corrupt directories list\n"));
break;
READ_ULEB (content_type, format, end);
READ_ULEB (form, format, end);
- if (data == end)
+ if (data >= end)
{
warn (_("Corrupt directories list\n"));
break;
NULL, 1, section,
NULL, '\t', -1);
}
- if (data == end)
+ if (data >= end)
{
warn (_("Corrupt directories list\n"));
break;
}
READ_ULEB (n_files, data, end);
- if (data == end && n_files > 0)
+ if (data >= end && n_files > 0)
{
warn (_("Corrupt file name list\n"));
break;
READ_ULEB (content_type, format, end);
READ_ULEB (form, format, end);
- if (data == end)
+ if (data >= end)
{
warn (_("Corrupt file name list\n"));
break;
NULL, 1, section,
NULL, '\t', -1);
}
- if (data == end)
+ if (data >= end)
{
warn (_("Corrupt file name list\n"));
break;
while (data < end && *data != 0)
{
- data += strnlen ((char *) data, end - data) + 1;
+ data += strnlen ((char *) data, end - data);
+ if (data < end)
+ data++;
n_directories++;
}
while (*ptr_directory_table != 0)
{
directory_table[i] = ptr_directory_table;
- ptr_directory_table += strnlen ((char *) ptr_directory_table,
- ptr_directory_table - end) + 1;
+ ptr_directory_table
+ += strlen ((char *) ptr_directory_table) + 1;
i++;
}
}
{
/* 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);
while (*ptr_file_name_table != 0)
{
file_table[i].name = ptr_file_name_table;
- ptr_file_name_table += strnlen ((char *) ptr_file_name_table,
- end - ptr_file_name_table) + 1;
+ ptr_file_name_table
+ += strlen ((char *) ptr_file_name_table) + 1;
/* We are not interested in directory, time or size. */
READ_ULEB (file_table[i].directory_index,
fileName = _("<unknown>");
fileNameLength = strlen (fileName);
-
- if ((fileNameLength > MAX_FILENAME_LENGTH) && (!do_wide))
+ newFileName = fileName;
+ if (fileNameLength > MAX_FILENAME_LENGTH && !do_wide)
{
newFileName = (char *) xmalloc (MAX_FILENAME_LENGTH + 1);
/* Truncate file name */
- strncpy (newFileName,
- fileName + fileNameLength - MAX_FILENAME_LENGTH,
- MAX_FILENAME_LENGTH + 1);
- /* FIXME: This is to pacify gcc-10 which can warn that the
- strncpy above might leave a non-NUL terminated string
- in newFileName. It won't, but gcc's analysis doesn't
- quite go far enough to discover this. */
+ memcpy (newFileName,
+ fileName + fileNameLength - MAX_FILENAME_LENGTH,
+ MAX_FILENAME_LENGTH);
newFileName[MAX_FILENAME_LENGTH] = 0;
}
- else
- {
- newFileName = (char *) xmalloc (fileNameLength + 1);
- strncpy (newFileName, fileName, fileNameLength + 1);
- }
/* A row with end_seq set to true has a meaningful address, but
the other information in the same row is not significant.
In such a row, print line as "-", and don't print
view/is_stmt. */
- if (!do_wide || (fileNameLength <= MAX_FILENAME_LENGTH))
+ if (!do_wide || fileNameLength <= MAX_FILENAME_LENGTH)
{
if (linfo.li_max_ops_per_insn == 1)
{
putchar ('\n');
}
- free (newFileName);
+ if (newFileName != fileName)
+ free (newFileName);
}
}
while (start < end)
{
unsigned char *data;
- unsigned long sec_off;
- unsigned int offset_size, initial_length_size;
+ unsigned long sec_off = start - section->start;
+ unsigned int offset_size;
SAFE_BYTE_GET_AND_INC (names.pn_length, start, 4, end);
if (names.pn_length == 0xffffffff)
{
SAFE_BYTE_GET_AND_INC (names.pn_length, start, 8, end);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
+ offset_size = 4;
- sec_off = start - section->start;
- if (sec_off + names.pn_length < sec_off
- || sec_off + names.pn_length > section->size)
+ if (names.pn_length > (size_t) (end - start))
{
warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
section->name,
- sec_off - initial_length_size,
+ sec_off,
dwarf_vmatoa ("x", names.pn_length));
break;
}
data = start;
start += names.pn_length;
- SAFE_BYTE_GET_AND_INC (names.pn_version, data, 2, end);
- SAFE_BYTE_GET_AND_INC (names.pn_offset, data, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (names.pn_version, data, 2, start);
+ SAFE_BYTE_GET_AND_INC (names.pn_offset, data, offset_size, start);
if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE
&& num_debug_info_entries > 0
warn (_(".debug_info offset of 0x%lx in %s section does not point to a CU header.\n"),
(unsigned long) names.pn_offset, section->name);
- SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, start);
printf (_(" Length: %ld\n"),
(long) names.pn_length);
bfd_size_type maxprint;
dwarf_vma offset;
- SAFE_BYTE_GET (offset, data, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (offset, data, offset_size, start);
if (offset == 0)
break;
- data += offset_size;
- if (data >= end)
+ if (data >= start)
break;
- maxprint = (end - data) - 1;
+ maxprint = (start - data) - 1;
if (is_gnu)
{
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, start);
maxprint --;
/* GCC computes the kind as the upper byte in the CU index
word, and then right shifts it by the CU index size.
printf (" %-6lx\t%.*s\n",
(unsigned long) offset, (int) maxprint, data);
- data += strnlen ((char *) data, maxprint) + 1;
- if (data >= end)
+ data += strnlen ((char *) data, maxprint);
+ if (data < start)
+ data++;
+ if (data >= start)
break;
}
}
case DW_MACINFO_define:
READ_ULEB (lineno, curr, end);
string = curr;
- curr += strnlen ((char *) string, end - string) + 1;
- printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
- lineno, string);
+ curr += strnlen ((char *) string, end - string);
+ printf (_(" DW_MACINFO_define - lineno : %d macro : %*s\n"),
+ lineno, (int) (curr - string), string);
+ if (curr < end)
+ curr++;
break;
case DW_MACINFO_undef:
READ_ULEB (lineno, curr, end);
string = curr;
- curr += strnlen ((char *) string, end - string) + 1;
- printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
- lineno, string);
+ curr += strnlen ((char *) string, end - string);
+ printf (_(" DW_MACINFO_undef - lineno : %d macro : %*s\n"),
+ lineno, (int) (curr - string), string);
+ if (curr < end)
+ curr++;
break;
case DW_MACINFO_vendor_ext:
READ_ULEB (constant, curr, end);
string = curr;
- curr += strnlen ((char *) string, end - string) + 1;
- printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
- constant, string);
+ curr += strnlen ((char *) string, end - string);
+ printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %*s\n"),
+ constant, (int) (curr - string), string);
+ if (curr < end)
+ curr++;
}
break;
}
{
struct dwarf_section *section = &debug_displays [line].section;
unsigned char *hdrptr, *dirtable, *file_name;
- unsigned int offset_size, initial_length_size;
+ unsigned int offset_size;
unsigned int version, opcode_base;
dwarf_vma length, diridx;
const unsigned char * end;
/* This section is 64-bit DWARF 3. */
SAFE_BYTE_GET_AND_INC (length, hdrptr, 8, end);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
- if (length + initial_length_size < length
- || length + initial_length_size > section->size)
+ offset_size = 4;
+
+ if (length > (size_t) (end - hdrptr)
+ || length < 2 + offset_size + 1 + 3 + 1)
return NULL;
+ end = hdrptr + length;
SAFE_BYTE_GET_AND_INC (version, hdrptr, 2, end);
if (version != 2 && version != 3 && version != 4)
hdrptr += 3; /* Skip default_is_stmt, line_base, line_range. */
SAFE_BYTE_GET_AND_INC (opcode_base, hdrptr, 1, end);
- if (opcode_base == 0)
+ if (opcode_base == 0
+ || opcode_base - 1 >= (size_t) (end - hdrptr))
return NULL;
hdrptr += opcode_base - 1;
- if (hdrptr >= end)
- return NULL;
dirtable = hdrptr;
/* Skip over dirname table. */
while (*hdrptr != '\0')
{
- hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+ hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+ if (hdrptr < end)
+ hdrptr++;
if (hdrptr >= end)
return NULL;
}
/* Now skip over preceding filename table entries. */
for (; hdrptr < end && *hdrptr != '\0' && fileidx > 1; fileidx--)
{
- hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+ hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+ if (hdrptr < end)
+ hdrptr++;
SKIP_ULEB (hdrptr, end);
SKIP_ULEB (hdrptr, end);
SKIP_ULEB (hdrptr, end);
return NULL;
file_name = hdrptr;
- hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+ hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+ if (hdrptr < end)
+ hdrptr++;
if (hdrptr >= end)
return NULL;
READ_ULEB (diridx, hdrptr, end);
if (diridx == 0)
return file_name;
for (; dirtable < end && *dirtable != '\0' && diridx > 1; diridx--)
- dirtable += strnlen ((char *) dirtable, end - dirtable) + 1;
+ {
+ dirtable += strnlen ((char *) dirtable, end - dirtable);
+ if (dirtable < end)
+ dirtable++;
+ }
if (dirtable >= end || *dirtable == '\0')
return NULL;
*dir_name = dirtable;
case DW_MACRO_define:
READ_ULEB (lineno, curr, end);
string = curr;
- curr += strnlen ((char *) string, end - string) + 1;
- printf (_(" DW_MACRO_define - lineno : %d macro : %s\n"),
- lineno, string);
+ curr += strnlen ((char *) string, end - string);
+ printf (_(" DW_MACRO_define - lineno : %d macro : %*s\n"),
+ lineno, (int) (curr - string), string);
+ if (curr < end)
+ curr++;
break;
case DW_MACRO_undef:
READ_ULEB (lineno, curr, end);
string = curr;
- curr += strnlen ((char *) string, end - string) + 1;
- printf (_(" DW_MACRO_undef - lineno : %d macro : %s\n"),
- lineno, string);
+ curr += strnlen ((char *) string, end - string);
+ printf (_(" DW_MACRO_undef - lineno : %d macro : %*s\n"),
+ lineno, (int) (curr - string), string);
+ if (curr < end)
+ curr++;
break;
case DW_MACRO_start_file:
{
abbrev_entry *entry;
unsigned char *start = section->start;
- const unsigned char *end = start + section->size;
introduce (section, false);
if (list == NULL)
{
list = new_abbrev_list (0, offset);
- start = process_abbrev_set (start, end, list);
+ start = process_abbrev_set (section, 0, section->size, offset, list);
list->start_of_next_abbrevs = start;
}
else
get_AT_name (attr->attribute),
get_FORM_name (attr->form));
if (attr->form == DW_FORM_implicit_const)
- printf (": %" BFD_VMA_FMT "d", attr->implicit_const);
+ printf (": %s", dwarf_vmatoa ("d", attr->implicit_const));
putchar ('\n');
}
}
dwarf_vma off = offset + (start - *start_ptr);
dwarf_vma vbegin = vm1, vend = vm1;
- if (start + 2 * pointer_size > section_end)
+ if (2 * pointer_size > (size_t) (section_end - start))
{
warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
(unsigned long) offset);
(unsigned long) off, 8, "");
}
- if (start + 2 > section_end)
+ if (2 > (size_t) (section_end - start))
{
warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
(unsigned long) offset);
SAFE_BYTE_GET_AND_INC (length, start, 2, section_end);
- if (start + length > section_end)
+ if (length > (size_t) (section_end - start))
{
warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
(unsigned long) offset);
&& llet != DW_LLE_start_length)
continue;
- if (start + 2 > section_end)
+ if (start == section_end)
{
warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
(unsigned long) offset);
break;
}
-
READ_ULEB (length, start, section_end);
+ if (length > (size_t) (section_end - start))
+ {
+ warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+ (unsigned long) offset);
+ break;
+ }
+
print_dwarf_vma (begin, pointer_size);
print_dwarf_vma (end, pointer_size);
return;
}
- if (start + 2 > section_end)
+ if (2 > (size_t) (section_end - start))
{
warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
(unsigned long) offset);
}
SAFE_BYTE_GET_AND_INC (length, start, 2, section_end);
- if (start + length > section_end)
+ if (length > (size_t) (section_end - start))
{
warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
(unsigned long) offset);
unsigned char address_size;
int excess;
unsigned int offset_size;
- unsigned int initial_length_size;
+ unsigned char *end_ranges;
hdrptr = start;
+ sec_off = hdrptr - section->start;
SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 4, end);
if (arange.ar_length == 0xffffffff)
{
SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 8, end);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
+ offset_size = 4;
- sec_off = hdrptr - section->start;
- if (sec_off + arange.ar_length < sec_off
- || sec_off + arange.ar_length > section->size)
+ if (arange.ar_length > (size_t) (end - hdrptr))
{
warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
section->name,
- sec_off - initial_length_size,
+ sec_off,
dwarf_vmatoa ("x", arange.ar_length));
break;
}
+ end_ranges = hdrptr + arange.ar_length;
- SAFE_BYTE_GET_AND_INC (arange.ar_version, hdrptr, 2, end);
- SAFE_BYTE_GET_AND_INC (arange.ar_info_offset, hdrptr, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (arange.ar_version, hdrptr, 2, end_ranges);
+ SAFE_BYTE_GET_AND_INC (arange.ar_info_offset, hdrptr, offset_size,
+ end_ranges);
if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE
&& num_debug_info_entries > 0
warn (_(".debug_info offset of 0x%lx in %s section does not point to a CU header.\n"),
(unsigned long) arange.ar_info_offset, section->name);
- SAFE_BYTE_GET_AND_INC (arange.ar_pointer_size, hdrptr, 1, end);
- SAFE_BYTE_GET_AND_INC (arange.ar_segment_size, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (arange.ar_pointer_size, hdrptr, 1, end_ranges);
+ SAFE_BYTE_GET_AND_INC (arange.ar_segment_size, hdrptr, 1, end_ranges);
if (arange.ar_version != 2 && arange.ar_version != 3)
{
if (excess)
addr_ranges += (2 * address_size) - excess;
- start += arange.ar_length + initial_length_size;
+ start = end_ranges;
- while (addr_ranges + 2 * address_size <= start)
+ while (2u * address_size <= (size_t) (start - addr_ranges))
{
- SAFE_BYTE_GET_AND_INC (address, addr_ranges, address_size, end);
- SAFE_BYTE_GET_AND_INC (length, addr_ranges, address_size, end);
+ SAFE_BYTE_GET_AND_INC (address, addr_ranges, address_size, start);
+ SAFE_BYTE_GET_AND_INC (length, addr_ranges, address_size, start);
printf (" ");
print_dwarf_vma (address, address_size);
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);
/* 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
}
else
{
- entries_end = curr + length;
+ if (length <= (dwarf_vma) (end - curr))
+ entries_end = curr + length;
+ else
+ {
+ warn (_("Section %s is too small %#lx\n"),
+ section->name, (unsigned long) section->size);
+ entries_end = end;
+ }
int version;
- SAFE_BYTE_GET_AND_INC (version, curr, 2, end);
+ SAFE_BYTE_GET_AND_INC (version, curr, 2, entries_end);
if (version != 5)
warn (_("Unexpected version number in str_offset header: %#x\n"), version);
int padding;
- SAFE_BYTE_GET_AND_INC (padding, curr, 2, end);
+ SAFE_BYTE_GET_AND_INC (padding, curr, 2, entries_end);
if (padding != 0)
warn (_("Unexpected value in str_offset header's padding field: %#x\n"), padding);
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;
- SAFE_BYTE_GET_AND_INC (offset, curr, entry_length, end);
+ SAFE_BYTE_GET_AND_INC (offset, curr, entry_length, entries_end);
if (dwo)
string = (const unsigned char *)
fetch_indexed_string (idx, NULL, entry_length, dwo);
/* Initialize it due to a false compiler warning. */
dwarf_vma begin = -1, length, end = -1;
- if (start + 1 > finish)
+ if (start >= finish)
{
warn (_("Range list starting at offset 0x%lx is not terminated.\n"),
offset);
if (is_rnglists)
{
dwarf_vma initial_length;
- unsigned int initial_length_size;
unsigned char segment_selector_size;
unsigned int offset_size, offset_entry_count;
unsigned short version;
/* This section is 64-bit DWARF 3. */
SAFE_BYTE_GET_AND_INC (initial_length, start, 8, finish);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
+ offset_size = 4;
- if (initial_length + initial_length_size > section->size)
+ if (initial_length > (size_t) (finish - start))
{
/* If the length field has a relocation against it, then we should
not complain if it is inaccurate (and probably negative).
It is copied from .debug_line handling code. */
if (reloc_at (section, (start - section->start) - offset_size))
{
- initial_length = (finish - start) - initial_length_size;
+ initial_length = finish - start;
}
else
{
return 0;
}
}
+ finish = start + initial_length;
/* Get and check the version number. */
SAFE_BYTE_GET_AND_INC (version, start, 2, finish);
pointer_size = (is_rnglists ? address_size : debug_info_p->pointer_size);
offset = range_entry->ranges_offset;
- next = section_begin + offset;
base_address = debug_info_p->base_address;
/* PR 17512: file: 001-101485-0.001:0.1. */
continue;
}
- if (next < section_begin || next >= finish)
+ if (offset > (size_t) (finish - section_begin))
{
warn (_("Corrupt offset (%#8.8lx) in range entry %u\n"),
(unsigned long) offset, i);
continue;
}
+ next = section_begin + offset;
/* If multiple DWARF entities reference the same range then we will
have multiple entries in the `range_entries' list for the same
}
if (strcmp (fc->augmentation, "eh") == 0)
- start += eh_addr_size;
+ {
+ if (eh_addr_size > (size_t) (end - start))
+ goto fail;
+ start += eh_addr_size;
+ }
if (version >= 4)
{
+ if (2 > (size_t) (end - start))
+ goto fail;
GET (fc->ptr_size, 1);
if (fc->ptr_size < 1 || fc->ptr_size > 8)
{
READ_ULEB (fc->code_factor, start, end);
READ_SLEB (fc->data_factor, start, end);
+ if (start >= end)
+ goto fail;
+
if (version == 1)
{
GET (fc->ra, 1);
if (fc->augmentation[0] == 'z')
{
+ if (start >= end)
+ goto fail;
READ_ULEB (augmentation_data_len, start, end);
augmentation_data = start;
/* PR 17512: file: 11042-2589-0.004. */
bfd_size_type augmentation_data_len = 0;
unsigned int encoded_ptr_size = saved_eh_addr_size;
unsigned int offset_size;
- unsigned int initial_length_size;
bool all_nops;
static Frame_Chunk fde_fc;
{
SAFE_BYTE_GET_AND_INC (length, start, 8, end);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
+ offset_size = 4;
- block_end = saved_start + length + initial_length_size;
- if (block_end > end || block_end < start)
+ if (length > (size_t) (end - start))
{
warn ("Invalid length 0x%s in FDE at %#08lx\n",
dwarf_vmatoa_1 (NULL, length, offset_size),
(unsigned long) (saved_start - section_start));
block_end = end;
}
+ else
+ block_end = start + length;
- SAFE_BYTE_GET_AND_INC (cie_id, start, offset_size, end);
+ SAFE_BYTE_GET_AND_INC (cie_id, start, offset_size, block_end);
if (is_eh ? (cie_id == 0) : ((offset_size == 4 && cie_id == DW_CIE_ID)
|| (offset_size == 8 && cie_id == DW64_CIE_ID)))
int version;
unsigned int mreg;
- start = read_cie (start, end, &cie, &version,
+ start = read_cie (start, block_end, &cie, &version,
&augmentation_data_len, &augmentation_data);
/* PR 17512: file: 027-135133-0.005. */
if (cie == NULL)
{
unsigned char *look_for;
unsigned long segment_selector;
+ dwarf_vma cie_off;
+ cie_off = cie_id;
if (is_eh)
{
dwarf_vma sign = (dwarf_vma) 1 << (offset_size * 8 - 1);
- look_for = start - 4 - ((cie_id ^ sign) - sign);
+ cie_off = (cie_off ^ sign) - sign;
+ cie_off = start - 4 - section_start - cie_off;
}
- else
- look_for = section_start + cie_id;
- if (look_for <= saved_start)
+ look_for = section_start + cie_off;
+ if (cie_off <= (dwarf_vma) (saved_start - section_start))
{
for (cie = chunks; cie ; cie = cie->next)
if (cie->chunk_start == look_for)
break;
}
+ else if (cie_off >= section->size)
+ cie = NULL;
else
{
for (cie = forward_refs; cie ; cie = cie->next)
SAFE_BYTE_GET_AND_INC (length, cie_scan, 8, end);
off_size = 8;
}
- if (length != 0)
+ if (length != 0 && length <= (size_t) (end - cie_scan))
{
dwarf_vma c_id;
+ unsigned char *cie_end = cie_scan + length;
- SAFE_BYTE_GET_AND_INC (c_id, cie_scan, off_size, end);
+ SAFE_BYTE_GET_AND_INC (c_id, cie_scan, off_size,
+ cie_end);
if (is_eh
? c_id == 0
: ((off_size == 4 && c_id == DW_CIE_ID)
int version;
unsigned int mreg;
- read_cie (cie_scan, end, &cie, &version,
+ read_cie (cie_scan, cie_end, &cie, &version,
&augmentation_data_len, &augmentation_data);
/* PR 17512: file: 3450-2098-0.004. */
if (cie == NULL)
warn (_("Probably corrupt segment size: %d - using 4 instead\n"), fc->segment_size);
fc->segment_size = 4;
}
- SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
+ SAFE_BYTE_GET_AND_INC (segment_selector, start,
+ fc->segment_size, block_end);
}
- fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section, end);
+ fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section,
+ block_end);
/* FIXME: It appears that sometimes the final pc_range value is
encoded in less than encoded_ptr_size bytes. See the x86_64
run of the "objcopy on compressed debug sections" test for an
example of this. */
- SAFE_BYTE_GET_AND_INC (fc->pc_range, start, encoded_ptr_size, end);
+ SAFE_BYTE_GET_AND_INC (fc->pc_range, start, encoded_ptr_size,
+ block_end);
if (cie->augmentation[0] == 'z')
{
- READ_ULEB (augmentation_data_len, start, end);
+ READ_ULEB (augmentation_data_len, start, block_end);
augmentation_data = start;
/* PR 17512 file: 722-8446-0.004 and PR 22386. */
- if (augmentation_data_len > (bfd_size_type) (end - start))
+ if (augmentation_data_len > (bfd_size_type) (block_end - start))
{
warn (_("Augmentation data too long: 0x%s, "
"expected at most %#lx\n"),
dwarf_vmatoa ("x", augmentation_data_len),
- (unsigned long) (end - start));
- start = end;
+ (unsigned long) (block_end - start));
+ start = block_end;
augmentation_data = NULL;
augmentation_data_len = 0;
}
{
unsigned int reg, op, opa;
unsigned long temp;
- unsigned char * new_start;
op = *start++;
opa = op & 0x3f;
case DW_CFA_advance_loc:
break;
case DW_CFA_offset:
- SKIP_ULEB (start, end);
+ SKIP_ULEB (start, block_end);
if (frame_need_space (fc, opa) >= 0)
fc->col_type[opa] = DW_CFA_undefined;
break;
fc->col_type[opa] = DW_CFA_undefined;
break;
case DW_CFA_set_loc:
- start += encoded_ptr_size;
+ if ((size_t) (block_end - start) < encoded_ptr_size)
+ start = block_end;
+ else
+ start += encoded_ptr_size;
break;
case DW_CFA_advance_loc1:
- start += 1;
+ if ((size_t) (block_end - start) < 1)
+ start = block_end;
+ else
+ start += 1;
break;
case DW_CFA_advance_loc2:
- start += 2;
+ if ((size_t) (block_end - start) < 2)
+ start = block_end;
+ else
+ start += 2;
break;
case DW_CFA_advance_loc4:
- start += 4;
+ if ((size_t) (block_end - start) < 4)
+ start = block_end;
+ else
+ start += 4;
break;
case DW_CFA_offset_extended:
case DW_CFA_val_offset:
- READ_ULEB (reg, start, end);
- SKIP_ULEB (start, end);
+ READ_ULEB (reg, start, block_end);
+ SKIP_ULEB (start, block_end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_restore_extended:
- READ_ULEB (reg, start, end);
+ READ_ULEB (reg, start, block_end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_undefined:
- READ_ULEB (reg, start, end);
+ READ_ULEB (reg, start, block_end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_same_value:
- READ_ULEB (reg, start, end);
+ READ_ULEB (reg, start, block_end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_register:
- READ_ULEB (reg, start, end);
- SKIP_ULEB (start, end);
+ READ_ULEB (reg, start, block_end);
+ SKIP_ULEB (start, block_end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa:
- SKIP_ULEB (start, end);
- SKIP_ULEB (start, end);
+ SKIP_ULEB (start, block_end);
+ SKIP_ULEB (start, block_end);
break;
case DW_CFA_def_cfa_register:
- SKIP_ULEB (start, end);
+ SKIP_ULEB (start, block_end);
break;
case DW_CFA_def_cfa_offset:
- SKIP_ULEB (start, end);
+ SKIP_ULEB (start, block_end);
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (temp, start, end);
- new_start = start + temp;
- if (new_start < start)
- {
- warn (_("Corrupt CFA_def expression value: %lu\n"), temp);
- start = block_end;
- }
+ READ_ULEB (temp, start, block_end);
+ if ((size_t) (block_end - start) < temp)
+ start = block_end;
else
- start = new_start;
+ start += temp;
break;
case DW_CFA_expression:
case DW_CFA_val_expression:
- READ_ULEB (reg, start, end);
- READ_ULEB (temp, start, end);
- new_start = start + temp;
- if (new_start < start)
- {
- /* PR 17512: file:306-192417-0.005. */
- warn (_("Corrupt CFA expression value: %lu\n"), temp);
- start = block_end;
- }
+ READ_ULEB (reg, start, block_end);
+ READ_ULEB (temp, start, block_end);
+ if ((size_t) (block_end - start) < temp)
+ start = block_end;
else
- start = new_start;
+ start += temp;
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_offset_extended_sf:
case DW_CFA_val_offset_sf:
- READ_ULEB (reg, start, end);
- SKIP_SLEB (start, end);
+ READ_ULEB (reg, start, block_end);
+ SKIP_SLEB (start, block_end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa_sf:
- SKIP_ULEB (start, end);
- SKIP_SLEB (start, end);
+ SKIP_ULEB (start, block_end);
+ SKIP_SLEB (start, block_end);
break;
case DW_CFA_def_cfa_offset_sf:
- SKIP_SLEB (start, end);
+ SKIP_SLEB (start, block_end);
break;
case DW_CFA_MIPS_advance_loc8:
- start += 8;
+ if ((size_t) (block_end - start) < 8)
+ start = block_end;
+ else
+ start += 8;
break;
case DW_CFA_GNU_args_size:
- SKIP_ULEB (start, end);
+ SKIP_ULEB (start, block_end);
break;
case DW_CFA_GNU_negative_offset_extended:
- READ_ULEB (reg, start, end);
- SKIP_ULEB (start, end);
+ READ_ULEB (reg, start, block_end);
+ SKIP_ULEB (start, block_end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
while (start < block_end)
{
- unsigned char * tmp;
unsigned op, opa;
unsigned long ul, roffs;
/* Note: It is tempting to use an unsigned long for 'reg' but there
break;
case DW_CFA_offset:
- READ_ULEB (roffs, start, end);
+ READ_ULEB (roffs, start, block_end);
if (opa >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_set_loc:
- vma = get_encoded_value (&start, fc->fde_encoding, section, block_end);
+ vma = get_encoded_value (&start, fc->fde_encoding, section,
+ block_end);
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
break;
case DW_CFA_advance_loc1:
- SAFE_BYTE_GET_AND_INC (ofs, start, 1, end);
+ SAFE_BYTE_GET_AND_INC (ofs, start, 1, block_end);
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
break;
case DW_CFA_offset_extended:
- READ_ULEB (reg, start, end);
- READ_ULEB (roffs, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_ULEB (roffs, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_val_offset:
- READ_ULEB (reg, start, end);
- READ_ULEB (roffs, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_ULEB (roffs, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_restore_extended:
- READ_ULEB (reg, start, end);
+ READ_ULEB (reg, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_undefined:
- READ_ULEB (reg, start, end);
+ READ_ULEB (reg, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_same_value:
- READ_ULEB (reg, start, end);
+ READ_ULEB (reg, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_register:
- READ_ULEB (reg, start, end);
- READ_ULEB (roffs, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_ULEB (roffs, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_def_cfa:
- READ_ULEB (fc->cfa_reg, start, end);
- READ_ULEB (fc->cfa_offset, start, end);
+ READ_ULEB (fc->cfa_reg, start, block_end);
+ READ_ULEB (fc->cfa_offset, start, block_end);
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa: %s ofs %d\n",
break;
case DW_CFA_def_cfa_register:
- READ_ULEB (fc->cfa_reg, start, end);
+ READ_ULEB (fc->cfa_reg, start, block_end);
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_register: %s\n",
break;
case DW_CFA_def_cfa_offset:
- READ_ULEB (fc->cfa_offset, start, end);
+ READ_ULEB (fc->cfa_offset, start, block_end);
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
break;
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (ul, start, end);
- if (start >= block_end || ul > (unsigned long) (block_end - start))
+ READ_ULEB (ul, start, block_end);
+ if (ul > (size_t) (block_end - start))
{
printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
break;
break;
case DW_CFA_expression:
- READ_ULEB (reg, start, end);
- READ_ULEB (ul, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_ULEB (ul, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
/* PR 17512: file: 069-133014-0.006. */
/* PR 17512: file: 98c02eb4. */
- tmp = start + ul;
- if (start >= block_end || tmp > block_end || tmp < start)
+ if (ul > (size_t) (block_end - start))
{
printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
break;
}
if (*reg_prefix == '\0')
fc->col_type[reg] = DW_CFA_expression;
- start = tmp;
+ start += ul;
break;
case DW_CFA_val_expression:
- READ_ULEB (reg, start, end);
- READ_ULEB (ul, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_ULEB (ul, start, block_end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
- tmp = start + ul;
- if (start >= block_end || tmp > block_end || tmp < start)
+ if (ul > (size_t) (block_end - start))
{
printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
break;
}
if (*reg_prefix == '\0')
fc->col_type[reg] = DW_CFA_val_expression;
- start = tmp;
+ start += ul;
break;
case DW_CFA_offset_extended_sf:
- READ_ULEB (reg, start, end);
- READ_SLEB (l, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_SLEB (l, start, block_end);
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_val_offset_sf:
- READ_ULEB (reg, start, end);
- READ_SLEB (l, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_SLEB (l, start, block_end);
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_def_cfa_sf:
- READ_ULEB (fc->cfa_reg, start, end);
- READ_ULEB (fc->cfa_offset, start, end);
+ READ_ULEB (fc->cfa_reg, start, block_end);
+ READ_ULEB (fc->cfa_offset, start, block_end);
fc->cfa_offset = fc->cfa_offset * fc->data_factor;
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
break;
case DW_CFA_def_cfa_offset_sf:
- READ_ULEB (fc->cfa_offset, start, end);
+ READ_ULEB (fc->cfa_offset, start, block_end);
fc->cfa_offset *= fc->data_factor;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
break;
case DW_CFA_GNU_args_size:
- READ_ULEB (ul, start, end);
+ READ_ULEB (ul, start, block_end);
if (! do_debug_frames_interp)
printf (" DW_CFA_GNU_args_size: %ld\n", ul);
break;
case DW_CFA_GNU_negative_offset_extended:
- READ_ULEB (reg, start, end);
- READ_SLEB (l, start, end);
+ READ_ULEB (reg, start, block_end);
+ READ_SLEB (l, start, block_end);
l = - l;
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
unsigned int offset_size;
uint16_t dwarf_version, padding;
uint32_t comp_unit_count, local_type_unit_count, foreign_type_unit_count;
- uint32_t bucket_count, name_count, abbrev_table_size;
+ uint64_t bucket_count, name_count, abbrev_table_size;
uint32_t augmentation_string_size;
unsigned int i;
- unsigned long sec_off;
bool augmentation_printable;
const char *augmentation_string;
+ size_t total;
unit_start = hdrptr;
}
else
offset_size = 4;
- unit_end = hdrptr + unit_length;
- sec_off = hdrptr - section->start;
- if (sec_off + unit_length < sec_off
- || sec_off + unit_length > section->size)
+ if (unit_length > (size_t) (section_end - hdrptr)
+ || unit_length < 2 + 2 + 4 * 7)
{
+ too_short:
warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
section->name,
(unsigned long) (unit_start - section->start),
dwarf_vmatoa ("x", unit_length));
return 0;
}
+ unit_end = hdrptr + unit_length;
/* Get and check the version number. */
SAFE_BYTE_GET_AND_INC (dwarf_version, hdrptr, 2, unit_end);
augmentation_string_size);
augmentation_string_size += (-augmentation_string_size) & 3;
}
+ if (augmentation_string_size > (size_t) (unit_end - hdrptr))
+ goto too_short;
printf (_("Augmentation string:"));
putchar ('\n');
printf (_("CU table:\n"));
+ if (_mul_overflow (comp_unit_count, offset_size, &total)
+ || total > (size_t) (unit_end - hdrptr))
+ goto too_short;
for (i = 0; i < comp_unit_count; i++)
{
uint64_t cu_offset;
putchar ('\n');
printf (_("TU table:\n"));
+ if (_mul_overflow (local_type_unit_count, offset_size, &total)
+ || total > (size_t) (unit_end - hdrptr))
+ goto too_short;
for (i = 0; i < local_type_unit_count; i++)
{
uint64_t tu_offset;
putchar ('\n');
printf (_("Foreign TU table:\n"));
+ if (_mul_overflow (foreign_type_unit_count, 8, &total)
+ || total > (size_t) (unit_end - hdrptr))
+ goto too_short;
for (i = 0; i < foreign_type_unit_count; i++)
{
uint64_t signature;
}
putchar ('\n');
+ uint64_t xtra = (bucket_count * sizeof (uint32_t)
+ + name_count * (sizeof (uint32_t) + 2 * offset_size)
+ + abbrev_table_size);
+ if (xtra > (size_t) (unit_end - hdrptr))
+ {
+ warn (_("Entry pool offset (0x%lx) exceeds unit size 0x%lx "
+ "for unit 0x%lx in the debug_names\n"),
+ (long) xtra,
+ (long) (unit_end - unit_start),
+ (long) (unit_start - section->start));
+ return 0;
+ }
const uint32_t *const hash_table_buckets = (uint32_t *) hdrptr;
hdrptr += bucket_count * sizeof (uint32_t);
const uint32_t *const hash_table_hashes = (uint32_t *) hdrptr;
hdrptr += abbrev_table_size;
const unsigned char *const abbrev_table_end = hdrptr;
unsigned char *const entry_pool = hdrptr;
- if (hdrptr > unit_end)
- {
- warn (_("Entry pool offset (0x%lx) exceeds unit size 0x%lx "
- "for unit 0x%lx in the debug_names\n"),
- (long) (hdrptr - section->start),
- (long) (unit_end - section->start),
- (long) (unit_start - section->start));
- return 0;
- }
size_t buckets_filled = 0;
size_t bucketi;
for (namei = 0; namei < name_count; ++namei)
{
uint64_t string_offset, entry_offset;
+ unsigned char *p;
- SAFE_BYTE_GET (string_offset,
- name_table_string_offsets + namei * offset_size,
- offset_size, unit_end);
- SAFE_BYTE_GET (entry_offset,
- name_table_entry_offsets + namei * offset_size,
- offset_size, unit_end);
+ p = name_table_string_offsets + namei * offset_size;
+ SAFE_BYTE_GET (string_offset, p, offset_size, unit_end);
+ p = name_table_entry_offsets + namei * offset_size;
+ SAFE_BYTE_GET (entry_offset, p, offset_size, unit_end);
printf ("[%3u] #%08x %s:", namei, hash_table_hashes[namei],
fetch_indirect_string (string_offset));
symbol_table = start + symbol_table_offset;
constant_pool = start + constant_pool_offset;
- if (address_table + address_table_size > section->start + section->size)
+ if (address_table_offset + address_table_size > section->size)
{
warn (_("Address table extends beyond end of section.\n"));
return 0;
|| cu_vector_offset != 0)
{
unsigned int j;
- unsigned char * adr;
- adr = constant_pool + name_offset;
/* PR 17531: file: 5b7b07ad. */
- if (adr < constant_pool || adr >= section->start + section->size)
+ if (name_offset >= section->size - constant_pool_offset)
{
printf (_("[%3u] <corrupt offset: %x>"), i, name_offset);
warn (_("Corrupt name offset of 0x%x found for symbol table slot %d\n"),
(int) (section->size - (constant_pool_offset + name_offset)),
constant_pool + name_offset);
- adr = constant_pool + cu_vector_offset;
- if (adr < constant_pool || adr >= section->start + section->size - 3)
+ if (section->size - constant_pool_offset < 4
+ || cu_vector_offset > section->size - constant_pool_offset - 4)
{
printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset);
warn (_("Corrupt CU vector offset of 0x%x found for symbol table slot %d\n"),
continue;
}
- num_cus = byte_get_little_endian (adr, 4);
+ num_cus = byte_get_little_endian (constant_pool + cu_vector_offset, 4);
- adr = constant_pool + cu_vector_offset + 4 + num_cus * 4;
- if (num_cus * 4 < num_cus
- || adr >= section->start + section->size
- || adr < constant_pool)
+ if ((uint64_t) num_cus * 4 > section->size - (constant_pool_offset
+ + cu_vector_offset + 4))
{
printf ("<invalid number of CUs: %d>\n", num_cus);
warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"),
unsigned int nslots;
unsigned int i;
unsigned int j;
- dwarf_vma signature_high;
- dwarf_vma signature_low;
- char buf[64];
+ dwarf_vma signature;
+ size_t total;
/* PR 17512: file: 002-168123-0.004. */
if (phdr == NULL)
return 0;
}
- SAFE_BYTE_GET (version, phdr, 4, limit);
+ phash = phdr;
+ SAFE_BYTE_GET_AND_INC (version, phash, 4, limit);
if (version >= 2)
- SAFE_BYTE_GET (ncols, phdr + 4, 4, limit);
- SAFE_BYTE_GET (nused, phdr + 8, 4, limit);
- SAFE_BYTE_GET (nslots, phdr + 12, 4, limit);
+ SAFE_BYTE_GET_AND_INC (ncols, phash, 4, limit);
+ SAFE_BYTE_GET_AND_INC (nused, phash, 4, limit);
+ SAFE_BYTE_GET_AND_INC (nslots, phash, 4, limit);
- phash = phdr + 16;
pindex = phash + (size_t) nslots * 8;
ppool = pindex + (size_t) nslots * 4;
}
/* PR 17531: file: 45d69832. */
- if ((size_t) nslots * 8 / 8 != nslots
- || phash < phdr || phash > limit
- || pindex < phash || pindex > limit
- || ppool < pindex || ppool > limit)
+ if (_mul_overflow ((size_t) nslots, 12, &total)
+ || total > (size_t) (limit - phash))
{
warn (ngettext ("Section %s is too small for %u slot\n",
"Section %s is too small for %u slots\n",
unsigned char *shndx_list;
unsigned int shndx;
- SAFE_BYTE_GET64 (phash, &signature_high, &signature_low, limit);
- if (signature_high != 0 || signature_low != 0)
+ SAFE_BYTE_GET (signature, phash, 8, limit);
+ if (signature != 0)
{
SAFE_BYTE_GET (j, pindex, 4, limit);
shndx_list = ppool + j * 4;
if (do_display)
printf (_(" [%3d] Signature: 0x%s Sections: "),
- i, dwarf_vmatoa64 (signature_high, signature_low,
- buf, sizeof (buf)));
+ i, dwarf_vmatoa ("x", signature));
for (;;)
{
if (shndx_list >= limit)
unsigned char *pi = pindex;
unsigned char *poffsets = ppool + (size_t) ncols * 4;
unsigned char *psizes = poffsets + (size_t) nused * ncols * 4;
- unsigned char *pend = psizes + (size_t) nused * ncols * 4;
bool is_tu_index;
struct cu_tu_set *this_set = NULL;
unsigned int row;
unsigned char *prow;
+ size_t temp;
is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
/* PR 17531: file: 0dd159bf.
Check for integer overflow (can occur when size_t is 32-bit)
with overlarge ncols or nused values. */
- if (ncols > 0
- && ((size_t) ncols * 4 / 4 != ncols
- || (size_t) nused * ncols * 4 / ((size_t) ncols * 4) != nused
- || poffsets < ppool || poffsets > limit
- || psizes < poffsets || psizes > limit
- || pend < psizes || pend > limit))
+ if (nused == -1u
+ || _mul_overflow ((size_t) ncols, 4, &temp)
+ || _mul_overflow ((size_t) nused + 1, temp, &total)
+ || total > (size_t) (limit - ppool))
{
warn (_("Section %s too small for offset and size tables\n"),
section->name);
{
for (j = 0; j < ncols; j++)
{
- SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
+ unsigned char *p = ppool + j * 4;
+ SAFE_BYTE_GET (dw_sect, p, 4, limit);
printf (" %8s", get_DW_SECT_short_name (dw_sect));
}
printf ("\n");
for (i = 0; i < nslots; i++)
{
- SAFE_BYTE_GET64 (ph, &signature_high, &signature_low, limit);
+ SAFE_BYTE_GET (signature, ph, 8, limit);
SAFE_BYTE_GET (row, pi, 4, limit);
if (row != 0)
{
size_t num_copy = sizeof (uint64_t);
- /* PR 23064: Beware of buffer overflow. */
- if (ph + num_copy < limit)
- memcpy (&this_set[row - 1].signature, ph, num_copy);
- else
- {
- warn (_("Signature (%p) extends beyond end of space in section\n"), ph);
- return 0;
- }
+ memcpy (&this_set[row - 1].signature, ph, num_copy);
}
prow = poffsets + (row - 1) * ncols * 4;
- /* PR 17531: file: b8ce60a8. */
- if (prow < poffsets || prow > limit)
- {
- warn (_("Row index (%u) * num columns (%u) > space remaining in section\n"),
- row, ncols);
- return 0;
- }
-
if (do_display)
printf (_(" [%3d] 0x%s"),
- i, dwarf_vmatoa64 (signature_high, signature_low,
- buf, sizeof (buf)));
+ i, dwarf_vmatoa ("x", signature));
for (j = 0; j < ncols; j++)
{
- SAFE_BYTE_GET (val, prow + j * 4, 4, limit);
+ unsigned char *p = prow + j * 4;
+ SAFE_BYTE_GET (val, p, 4, limit);
if (do_display)
printf (" %8d", val);
else
{
- SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
+ p = ppool + j * 4;
+ SAFE_BYTE_GET (dw_sect, p, 4, limit);
/* PR 17531: file: 10796eb3. */
if (dw_sect >= DW_SECT_MAX)
for (j = 0; j < ncols; j++)
{
- SAFE_BYTE_GET (val, ppool + j * 4, 4, limit);
+ unsigned char *p = ppool + j * 4;
+ SAFE_BYTE_GET (val, p, 4, limit);
if (do_display)
printf (" %8s", get_DW_SECT_short_name (val));
}
for (i = 0; i < nslots; i++)
{
- SAFE_BYTE_GET64 (ph, &signature_high, &signature_low, limit);
+ SAFE_BYTE_GET (signature, ph, 8, limit);
SAFE_BYTE_GET (row, pi, 4, limit);
if (row != 0)
if (do_display)
printf (_(" [%3d] 0x%s"),
- i, dwarf_vmatoa64 (signature_high, signature_low,
- buf, sizeof (buf)));
+ i, dwarf_vmatoa ("x", signature));
for (j = 0; j < ncols; j++)
{
- SAFE_BYTE_GET (val, prow + j * 4, 4, limit);
+ unsigned char *p = prow + j * 4;
+ SAFE_BYTE_GET (val, p, 4, limit);
if (do_display)
printf (" %8d", val);
else
{
- SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
+ p = ppool + j * 4;
+ SAFE_BYTE_GET (dw_sect, p, 4, limit);
if (dw_sect >= DW_SECT_MAX)
warn (_("Overlarge Dwarf section index detected: %u\n"), dw_sect);
else