From 0c5882475c48596b92ed08a7ccfa6347d44f8f65 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 26 Mar 2013 22:51:12 +0000 Subject: [PATCH] PR binutils/15205 * dwarf.c (SAFE_BYTE_GET): New macro - checks remaining buffer space before calling byte_get. (SAFE_BYTE_GET_AND_INC): New macro. (SAFE_SIGNED_BYTE_GET): New macro. (SAFE_SIGNED_BYTE_GET_AND_INC): New macro. (SAFE_BYTE_GET64): New macro. (process_extened_line_op): Use new macros. Use strnlen when appropriate. (fetch_indirect_string): Likewise. (get_FORM_name): Likewise. (decode_location_expression): Likewise. (read_and_display_attr_value): Likewise. (process_debug_info): Likewise. (display_debug_lines_raw): Likewise. (display_debug_lines_decoded): Likewise. (display_debug_pubnames): Likewise. (display_debug_macinfo): Likewise. (get_line_filename_and_dirname): Likewise. (display_debug_macro): Likewise. (display_loc_list): Likewise. (display_loc_list_dwo): Likewise. (display_debug_aranges): Likewise. (display_debug_ranges): Likewise. (frame_display_row): Likewise. (display_debug_frames): Likewise. --- binutils/ChangeLog | 29 +++ binutils/dwarf.c | 578 +++++++++++++++++++++++---------------------- 2 files changed, 330 insertions(+), 277 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index ebede029adb..35233c11485 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,32 @@ +2013-03-26 Nick Clifton + + PR binutils/15205 + * dwarf.c (SAFE_BYTE_GET): New macro - checks remaining buffer + space before calling byte_get. + (SAFE_BYTE_GET_AND_INC): New macro. + (SAFE_SIGNED_BYTE_GET): New macro. + (SAFE_SIGNED_BYTE_GET_AND_INC): New macro. + (SAFE_BYTE_GET64): New macro. + (process_extened_line_op): Use new macros. Use strnlen when + appropriate. + (fetch_indirect_string): Likewise. + (get_FORM_name): Likewise. + (decode_location_expression): Likewise. + (read_and_display_attr_value): Likewise. + (process_debug_info): Likewise. + (display_debug_lines_raw): Likewise. + (display_debug_lines_decoded): Likewise. + (display_debug_pubnames): Likewise. + (display_debug_macinfo): Likewise. + (get_line_filename_and_dirname): Likewise. + (display_debug_macro): Likewise. + (display_loc_list): Likewise. + (display_loc_list_dwo): Likewise. + (display_debug_aranges): Likewise. + (display_debug_ranges): Likewise. + (frame_display_row): Likewise. + (display_debug_frames): Likewise. + 2013-03-25 Nick Clifton PR binutils/15202 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 4a11aa5c5da..24a5906f846 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -278,6 +278,73 @@ read_uleb128 (unsigned char * data, return read_leb128 (data, length_return, FALSE, end); } +#define SAFE_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 ((PTR), amount); \ + else \ + VAL = 0; \ + } \ + while (0) + +#define SAFE_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END) \ + do \ + { \ + SAFE_BYTE_GET (VAL, PTR, AMOUNT, END); \ + PTR += AMOUNT; \ + } \ + while (0) + +#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) + +#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 \ + { \ + PTR = END; \ + * (LOW) = * (HIGH) = 0; \ + } \ + } \ + while (0) + typedef struct State_Machine_Registers { dwarf_vma address; @@ -346,7 +413,7 @@ process_extended_line_op (unsigned char * data, break; case DW_LNE_set_address: - adr = byte_get (data, len - bytes_read - 1); + SAFE_BYTE_GET (adr, data, len - bytes_read - 1, end); printf (_("set Address to 0x%s\n"), dwarf_vmatoa ("x", adr)); state_machine_regs.address = adr; state_machine_regs.op_index = 0; @@ -358,7 +425,7 @@ process_extended_line_op (unsigned char * data, printf (" %d\t", ++state_machine_regs.last_file_entry); name = data; - data += strlen ((char *) data) + 1; + data += strnlen ((char *) data, end - data) + 1; printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); data += bytes_read; printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); @@ -478,13 +545,13 @@ process_extended_line_op (unsigned char * data, return len; } -static const char * +static const unsigned char * fetch_indirect_string (dwarf_vma offset) { struct dwarf_section *section = &debug_displays [str].section; if (section->start == NULL) - return _(""); + return (const unsigned char *) _(""); /* DWARF sections under Mach-O have non-zero addresses. */ offset -= section->address; @@ -492,10 +559,10 @@ fetch_indirect_string (dwarf_vma offset) { warn (_("DW_FORM_strp offset too big: %s\n"), dwarf_vmatoa ("x", offset)); - return _(""); + return (const unsigned char *) _(""); } - return (const char *) section->start + offset; + return (const unsigned char *) section->start + offset; } static const char * @@ -757,10 +824,17 @@ get_FORM_name (unsigned long form) } static unsigned char * -display_block (unsigned char *data, dwarf_vma length) +display_block (unsigned char *data, + dwarf_vma length, + const unsigned char * const end) { + dwarf_vma maxlen; + printf (_(" %s byte block: "), dwarf_vmatoa ("u", length)); + maxlen = (dwarf_vma) (end - data); + length = length > maxlen ? maxlen : length; + while (length --) printf ("%lx ", (unsigned long) byte_get (data++, 1)); @@ -779,6 +853,7 @@ decode_location_expression (unsigned char * data, unsigned op; unsigned int bytes_read; dwarf_vma uvalue; + dwarf_signed_vma svalue; unsigned char *end = data + length; int need_frame_base = 0; @@ -789,44 +864,47 @@ decode_location_expression (unsigned char * data, switch (op) { case DW_OP_addr: - printf ("DW_OP_addr: %s", - dwarf_vmatoa ("x", byte_get (data, pointer_size))); - data += pointer_size; + SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end); + printf ("DW_OP_addr: %s", dwarf_vmatoa ("x", uvalue)); break; case DW_OP_deref: printf ("DW_OP_deref"); break; case DW_OP_const1u: - printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data++, 1)); + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + printf ("DW_OP_const1u: %lu", (unsigned long) uvalue); break; case DW_OP_const1s: - printf ("DW_OP_const1s: %ld", (long) byte_get_signed (data++, 1)); + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 1, end); + printf ("DW_OP_const1s: %ld", (long) svalue); break; case DW_OP_const2u: - printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2)); - data += 2; + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + printf ("DW_OP_const2u: %lu", (unsigned long) uvalue); break; case DW_OP_const2s: - printf ("DW_OP_const2s: %ld", (long) byte_get_signed (data, 2)); - data += 2; + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end); + printf ("DW_OP_const2s: %ld", (long) svalue); break; case DW_OP_const4u: - printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4)); - data += 4; + SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end); + printf ("DW_OP_const4u: %lu", (unsigned long) uvalue); break; case DW_OP_const4s: - printf ("DW_OP_const4s: %ld", (long) byte_get_signed (data, 4)); - data += 4; + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end); + printf ("DW_OP_const4s: %ld", (long) svalue); break; case DW_OP_const8u: - printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4), - (unsigned long) byte_get (data + 4, 4)); - data += 8; + SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end); + printf ("DW_OP_const8u: %lu ", (unsigned long) uvalue); + SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end); + printf ("%lu", (unsigned long) uvalue); break; case DW_OP_const8s: - printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4), - (long) byte_get (data + 4, 4)); - data += 8; + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end); + printf ("DW_OP_const8s: %ld ", (long) svalue); + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end); + printf ("%ld", (long) svalue); break; case DW_OP_constu: printf ("DW_OP_constu: %s", @@ -848,7 +926,8 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_over"); break; case DW_OP_pick: - printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data++, 1)); + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + printf ("DW_OP_pick: %ld", (unsigned long) uvalue); break; case DW_OP_swap: printf ("DW_OP_swap"); @@ -907,8 +986,8 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_xor"); break; case DW_OP_bra: - printf ("DW_OP_bra: %ld", (long) byte_get_signed (data, 2)); - data += 2; + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end); + printf ("DW_OP_bra: %ld", (long) svalue); break; case DW_OP_eq: printf ("DW_OP_eq"); @@ -929,8 +1008,8 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_ne"); break; case DW_OP_skip: - printf ("DW_OP_skip: %ld", (long) byte_get_signed (data, 2)); - data += 2; + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end); + printf ("DW_OP_skip: %ld", (long) svalue); break; case DW_OP_lit0: @@ -1069,10 +1148,12 @@ decode_location_expression (unsigned char * data, data += bytes_read; break; case DW_OP_deref_size: - printf ("DW_OP_deref_size: %ld", (long) byte_get (data++, 1)); + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + printf ("DW_OP_deref_size: %ld", (long) uvalue); break; case DW_OP_xderef_size: - printf ("DW_OP_xderef_size: %ld", (long) byte_get (data++, 1)); + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + printf ("DW_OP_xderef_size: %ld", (long) uvalue); break; case DW_OP_nop: printf ("DW_OP_nop"); @@ -1085,18 +1166,16 @@ decode_location_expression (unsigned char * data, case DW_OP_call2: /* XXX: Strictly speaking for 64-bit DWARF3 files this ought to be an 8-byte wide computation. */ + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end); printf ("DW_OP_call2: <0x%s>", - dwarf_vmatoa ("x", (dwarf_signed_vma) byte_get (data, 2) - + cu_offset)); - data += 2; + dwarf_vmatoa ("x", svalue + cu_offset)); break; case DW_OP_call4: /* XXX: Strictly speaking for 64-bit DWARF3 files this ought to be an 8-byte wide computation. */ + SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end); printf ("DW_OP_call4: <0x%s>", - dwarf_vmatoa ("x", (dwarf_signed_vma) byte_get (data, 4) - + cu_offset)); - data += 4; + dwarf_vmatoa ("x", svalue + cu_offset)); break; case DW_OP_call_ref: /* XXX: Strictly speaking for 64-bit DWARF3 files @@ -1109,16 +1188,13 @@ decode_location_expression (unsigned char * data, } if (dwarf_version == 2) { - printf ("DW_OP_call_ref: <0x%s>", - dwarf_vmatoa ("x", byte_get (data, pointer_size))); - data += pointer_size; + SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end); } else { - printf ("DW_OP_call_ref: <0x%s>", - dwarf_vmatoa ("x", byte_get (data, offset_size))); - data += offset_size; + SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end); } + printf ("DW_OP_call_ref: <0x%s>", dwarf_vmatoa ("x", uvalue)); break; case DW_OP_form_tls_address: printf ("DW_OP_form_tls_address"); @@ -1145,7 +1221,7 @@ decode_location_expression (unsigned char * data, printf ("DW_OP_implicit_value"); uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; - display_block (data, uvalue); + display_block (data, uvalue, end); data += uvalue; break; @@ -1181,20 +1257,17 @@ decode_location_expression (unsigned char * data, } if (dwarf_version == 2) { - printf ("DW_OP_GNU_implicit_pointer: <0x%s> %s", - dwarf_vmatoa ("x", byte_get (data, pointer_size)), - dwarf_vmatoa ("d", read_sleb128 (data + pointer_size, - &bytes_read, end))); - data += pointer_size + bytes_read; + SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end); } else { - printf ("DW_OP_GNU_implicit_pointer: <0x%s> %s", - dwarf_vmatoa ("x", byte_get (data, offset_size)), - dwarf_vmatoa ("d", read_sleb128 (data + offset_size, - &bytes_read, end))); - data += offset_size + bytes_read; + SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end); } + printf ("DW_OP_GNU_implicit_pointer: <0x%s> %s", + dwarf_vmatoa ("x", uvalue), + dwarf_vmatoa ("d", read_sleb128 (data, + &bytes_read, end))); + data += bytes_read; break; case DW_OP_GNU_entry_value: uvalue = read_uleb128 (data, &bytes_read, end); @@ -1212,8 +1285,8 @@ decode_location_expression (unsigned char * data, data += bytes_read; printf ("DW_OP_GNU_const_type: <0x%s> ", dwarf_vmatoa ("x", cu_offset + uvalue)); - uvalue = byte_get (data++, 1); - display_block (data, uvalue); + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + display_block (data, uvalue, end); data += uvalue; break; case DW_OP_GNU_regval_type: @@ -1226,7 +1299,8 @@ decode_location_expression (unsigned char * data, printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue)); break; case DW_OP_GNU_deref_type: - printf ("DW_OP_GNU_deref_type: %ld", (long) byte_get (data++, 1)); + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + printf ("DW_OP_GNU_deref_type: %ld", (long) uvalue); uvalue = read_uleb128 (data, &bytes_read, end); data += bytes_read; printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue)); @@ -1244,9 +1318,9 @@ decode_location_expression (unsigned char * data, dwarf_vmatoa ("x", uvalue ? cu_offset + uvalue : 0)); break; case DW_OP_GNU_parameter_ref: + SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end); printf ("DW_OP_GNU_parameter_ref: <0x%s>", - dwarf_vmatoa ("x", cu_offset + byte_get (data, 4))); - data += 4; + dwarf_vmatoa ("x", cu_offset + uvalue)); break; case DW_OP_GNU_addr_index: uvalue = read_uleb128 (data, &bytes_read, end); @@ -1363,6 +1437,12 @@ read_and_display_attr_value (unsigned long attribute, unsigned char * orig_data = data; unsigned int bytes_read; + if (data == end) + { + warn (_("corrupt attribute\n")); + return data; + } + switch (form) { default: @@ -1370,31 +1450,23 @@ read_and_display_attr_value (unsigned long attribute, case DW_FORM_ref_addr: if (dwarf_version == 2) - { - uvalue = byte_get (data, pointer_size); - data += pointer_size; - } + SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end); else if (dwarf_version == 3 || dwarf_version == 4) - { - uvalue = byte_get (data, offset_size); - data += offset_size; - } + SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end); else error (_("Internal error: DWARF version is not 2, 3 or 4.\n")); break; case DW_FORM_addr: - uvalue = byte_get (data, pointer_size); - data += pointer_size; + SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end); break; case DW_FORM_strp: case DW_FORM_sec_offset: case DW_FORM_GNU_ref_alt: case DW_FORM_GNU_strp_alt: - uvalue = byte_get (data, offset_size); - data += offset_size; + SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end); break; case DW_FORM_flag_present: @@ -1404,19 +1476,17 @@ read_and_display_attr_value (unsigned long attribute, case DW_FORM_ref1: case DW_FORM_flag: case DW_FORM_data1: - uvalue = byte_get (data++, 1); + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); break; case DW_FORM_ref2: case DW_FORM_data2: - uvalue = byte_get (data, 2); - data += 2; + SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end); break; case DW_FORM_ref4: case DW_FORM_data4: - uvalue = byte_get (data, 4); - data += 4; + SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end); break; case DW_FORM_sdata: @@ -1495,25 +1565,28 @@ read_and_display_attr_value (unsigned long attribute, dwarf_vma high_bits; char buf[64]; - byte_get_64 (data, &high_bits, &uvalue); + SAFE_BYTE_GET64 (data, &high_bits, &uvalue, end); + printf (" 0x%s", dwarf_vmatoa64 (high_bits, uvalue, buf, sizeof (buf))); } + if ((do_loc || do_debug_loc || do_debug_ranges) && num_debug_info_entries == 0) { if (sizeof (uvalue) == 8) - uvalue = byte_get (data, 8); + SAFE_BYTE_GET (uvalue, data, 8, end); else error (_("DW_FORM_data8 is unsupported when sizeof (dwarf_vma) != 8\n")); } + data += 8; break; case DW_FORM_string: if (!do_loc) - printf (" %s", data); - data += strlen ((char *) data) + 1; + printf (" %.*s", end - data, data); + data += strnlen ((char *) data, end - data) + 1; break; case DW_FORM_block: @@ -1523,34 +1596,34 @@ read_and_display_attr_value (unsigned long attribute, if (do_loc) data = block_start + uvalue; else - data = display_block (block_start, uvalue); + data = display_block (block_start, uvalue, end); break; case DW_FORM_block1: - uvalue = byte_get (data, 1); + SAFE_BYTE_GET (uvalue, data, 1, end); block_start = data + 1; if (do_loc) data = block_start + uvalue; else - data = display_block (block_start, uvalue); + data = display_block (block_start, uvalue, end); break; case DW_FORM_block2: - uvalue = byte_get (data, 2); + SAFE_BYTE_GET (uvalue, data, 2, end); block_start = data + 2; if (do_loc) data = block_start + uvalue; else - data = display_block (block_start, uvalue); + data = display_block (block_start, uvalue, end); break; case DW_FORM_block4: - uvalue = byte_get (data, 4); + SAFE_BYTE_GET (uvalue, data, 4, end); block_start = data + 4; if (do_loc) data = block_start + uvalue; else - data = display_block (block_start, uvalue); + data = display_block (block_start, uvalue, end); break; case DW_FORM_strp: @@ -1588,7 +1661,7 @@ read_and_display_attr_value (unsigned long attribute, dwarf_vma high_bits; char buf[64]; - byte_get_64 (data, &high_bits, &uvalue); + SAFE_BYTE_GET64 (data, &high_bits, &uvalue, end); printf (" signature: 0x%s", dwarf_vmatoa64 (high_bits, uvalue, buf, sizeof (buf))); } @@ -2045,11 +2118,11 @@ process_debug_info (struct dwarf_section *section, /* 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. */ - length = byte_get (section_begin, 4); + SAFE_BYTE_GET (length, section_begin, 4, end); if (length == 0xffffffff) { - length = byte_get (section_begin + 4, 8); + SAFE_BYTE_GET (length, section_begin + 4, 8, end); section_begin += length + 12; } else if (length >= 0xfffffff0 && length < 0xffffffff) @@ -2127,13 +2200,11 @@ process_debug_info (struct dwarf_section *section, hdrptr = start; - compunit.cu_length = byte_get (hdrptr, 4); - hdrptr += 4; + SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 4, end); if (compunit.cu_length == 0xffffffff) { - compunit.cu_length = byte_get (hdrptr, 8); - hdrptr += 8; + SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 8, end); offset_size = 8; initial_length_size = 12; } @@ -2143,15 +2214,13 @@ process_debug_info (struct dwarf_section *section, initial_length_size = 4; } - compunit.cu_version = byte_get (hdrptr, 2); - hdrptr += 2; + SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end); cu_offset = start - section_begin; this_set = find_cu_tu_set_v2 (cu_offset, do_types); - compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size); - hdrptr += offset_size; + SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end); if (this_set == NULL) { @@ -2164,15 +2233,12 @@ process_debug_info (struct dwarf_section *section, abbrev_size = this_set->section_sizes [DW_SECT_ABBREV]; } - compunit.cu_pointer_size = byte_get (hdrptr, 1); - hdrptr += 1; + SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end); if (do_types) { - byte_get_64 (hdrptr, &signature_high, &signature_low); - hdrptr += 8; - type_offset = byte_get (hdrptr, offset_size); - hdrptr += offset_size; + SAFE_BYTE_GET64 (hdrptr, &signature_high, &signature_low, end); + SAFE_BYTE_GET_AND_INC (type_offset, hdrptr, offset_size, end); } if ((do_loc || do_debug_loc || do_debug_ranges) @@ -2498,14 +2564,12 @@ display_debug_lines_raw (struct dwarf_section *section, hdroff = hdrptr - start; /* Check the length of the block. */ - linfo.li_length = byte_get (hdrptr, 4); - hdrptr += 4; + SAFE_BYTE_GET_AND_INC (linfo.li_length, hdrptr, 4, end); if (linfo.li_length == 0xffffffff) { /* This section is 64-bit DWARF 3. */ - linfo.li_length = byte_get (hdrptr, 8); - hdrptr += 8; + SAFE_BYTE_GET_AND_INC (linfo.li_length, hdrptr, 8, end); offset_size = 8; initial_length_size = 12; } @@ -2524,8 +2588,7 @@ display_debug_lines_raw (struct dwarf_section *section, } /* Check its version number. */ - linfo.li_version = byte_get (hdrptr, 2); - hdrptr += 2; + SAFE_BYTE_GET_AND_INC (linfo.li_version, hdrptr, 2, end); if (linfo.li_version != 2 && linfo.li_version != 3 && linfo.li_version != 4) @@ -2534,14 +2597,13 @@ display_debug_lines_raw (struct dwarf_section *section, return 0; } - linfo.li_prologue_length = byte_get (hdrptr, offset_size); - hdrptr += offset_size; - linfo.li_min_insn_length = byte_get (hdrptr, 1); - hdrptr++; + SAFE_BYTE_GET_AND_INC (linfo.li_prologue_length, hdrptr, offset_size, end); + SAFE_BYTE_GET_AND_INC (linfo.li_min_insn_length, hdrptr, 1, end); + if (linfo.li_version >= 4) { - linfo.li_max_ops_per_insn = byte_get (hdrptr, 1); - hdrptr++; + SAFE_BYTE_GET_AND_INC (linfo.li_max_ops_per_insn, hdrptr, 1, end); + if (linfo.li_max_ops_per_insn == 0) { warn (_("Invalid maximum operations per insn.\n")); @@ -2550,14 +2612,11 @@ display_debug_lines_raw (struct dwarf_section *section, } else linfo.li_max_ops_per_insn = 1; - linfo.li_default_is_stmt = byte_get (hdrptr, 1); - hdrptr++; - linfo.li_line_base = byte_get (hdrptr, 1); - hdrptr++; - linfo.li_line_range = byte_get (hdrptr, 1); - hdrptr++; - linfo.li_opcode_base = byte_get (hdrptr, 1); - hdrptr++; + + SAFE_BYTE_GET_AND_INC (linfo.li_default_is_stmt, hdrptr, 1, end); + SAFE_BYTE_GET_AND_INC (linfo.li_line_base, hdrptr, 1, 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); /* Sign extend the line base field. */ linfo.li_line_base <<= 24; @@ -2600,7 +2659,7 @@ display_debug_lines_raw (struct dwarf_section *section, { printf (" %s\n", data); - data += strlen ((char *) data) + 1; + data += strnlen ((char *) data, end - data) + 1; } } @@ -2622,7 +2681,7 @@ display_debug_lines_raw (struct dwarf_section *section, printf (" %d\t", ++state_machine_regs.last_file_entry); name = data; - data += strlen ((char *) data) + 1; + data += strnlen ((char *) data, end - data) + 1; printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end))); @@ -2792,8 +2851,7 @@ display_debug_lines_raw (struct dwarf_section *section, break; case DW_LNS_fixed_advance_pc: - uladv = byte_get (data, 2); - data += 2; + SAFE_BYTE_GET_AND_INC (uladv, data, 2, end); state_machine_regs.address += uladv; state_machine_regs.op_index = 0; printf (_(" Advance PC by fixed size amount %s to 0x%s\n"), @@ -2874,14 +2932,12 @@ display_debug_lines_decoded (struct dwarf_section *section, (section 6.2.4 in the Dwarf3 doc). */ /* Get the length of this CU's line number information block. */ - linfo.li_length = byte_get (hdrptr, 4); - hdrptr += 4; + SAFE_BYTE_GET_AND_INC (linfo.li_length, hdrptr, 4, end); if (linfo.li_length == 0xffffffff) { /* This section is 64-bit DWARF 3. */ - linfo.li_length = byte_get (hdrptr, 8); - hdrptr += 8; + SAFE_BYTE_GET_AND_INC (linfo.li_length, hdrptr, 8, end); offset_size = 8; initial_length_size = 12; } @@ -2899,8 +2955,7 @@ display_debug_lines_decoded (struct dwarf_section *section, } /* Get this CU's Line Number Block version number. */ - linfo.li_version = byte_get (hdrptr, 2); - hdrptr += 2; + SAFE_BYTE_GET_AND_INC (linfo.li_version, hdrptr, 2, end); if (linfo.li_version != 2 && linfo.li_version != 3 && linfo.li_version != 4) @@ -2910,14 +2965,12 @@ display_debug_lines_decoded (struct dwarf_section *section, return 0; } - linfo.li_prologue_length = byte_get (hdrptr, offset_size); - hdrptr += offset_size; - linfo.li_min_insn_length = byte_get (hdrptr, 1); - hdrptr++; + SAFE_BYTE_GET_AND_INC (linfo.li_prologue_length, hdrptr, offset_size, end); + SAFE_BYTE_GET_AND_INC (linfo.li_min_insn_length, hdrptr, 1, end); + if (linfo.li_version >= 4) { - linfo.li_max_ops_per_insn = byte_get (hdrptr, 1); - hdrptr++; + SAFE_BYTE_GET_AND_INC (linfo.li_max_ops_per_insn, hdrptr, 1, end); if (linfo.li_max_ops_per_insn == 0) { warn (_("Invalid maximum operations per insn.\n")); @@ -2926,14 +2979,11 @@ display_debug_lines_decoded (struct dwarf_section *section, } else linfo.li_max_ops_per_insn = 1; - linfo.li_default_is_stmt = byte_get (hdrptr, 1); - hdrptr++; - linfo.li_line_base = byte_get (hdrptr, 1); - hdrptr++; - linfo.li_line_range = byte_get (hdrptr, 1); - hdrptr++; - linfo.li_opcode_base = byte_get (hdrptr, 1); - hdrptr++; + + SAFE_BYTE_GET_AND_INC (linfo.li_default_is_stmt, hdrptr, 1, end); + SAFE_BYTE_GET_AND_INC (linfo.li_line_base, hdrptr, 1, 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); /* Sign extend the line base field. */ linfo.li_line_base <<= 24; @@ -2955,7 +3005,7 @@ display_debug_lines_decoded (struct dwarf_section *section, while (*data != 0) { - data += strlen ((char *) data) + 1; + data += strnlen ((char *) data, end - data) + 1; n_directories++; } @@ -2967,7 +3017,8 @@ display_debug_lines_decoded (struct dwarf_section *section, while (*ptr_directory_table != 0) { directory_table[i] = ptr_directory_table; - ptr_directory_table += strlen ((char *) ptr_directory_table) + 1; + ptr_directory_table += strnlen ((char *) ptr_directory_table, + ptr_directory_table - end) + 1; i++; } } @@ -2985,7 +3036,7 @@ display_debug_lines_decoded (struct dwarf_section *section, /* Skip Name, directory index, last modification time and length of file. */ - data += strlen ((char *) data) + 1; + data += strnlen ((char *) data, end - data) + 1; read_uleb128 (data, & bytes_read, end); data += bytes_read; read_uleb128 (data, & bytes_read, end); @@ -3005,7 +3056,8 @@ display_debug_lines_decoded (struct dwarf_section *section, unsigned int bytes_read; file_table[i].name = ptr_file_name_table; - ptr_file_name_table += strlen ((char *) ptr_file_name_table) + 1; + ptr_file_name_table += strnlen ((char *) ptr_file_name_table, + end - ptr_file_name_table) + 1; /* We are not interested in directory, time or size. */ file_table[i].directory_index = read_uleb128 (ptr_file_name_table, @@ -3030,6 +3082,7 @@ display_debug_lines_decoded (struct dwarf_section *section, { unsigned int ix = file_table[0].directory_index; const char *directory = ix ? (char *)directory_table[ix - 1] : "."; + if (do_wide || strlen (directory) < 76) printf (_("CU: %s/%s:\n"), directory, file_table[0].name); else @@ -3103,8 +3156,9 @@ display_debug_lines_decoded (struct dwarf_section *section, reset_state_machine (linfo.li_default_is_stmt); break; case DW_LNE_set_address: - state_machine_regs.address = - byte_get (op_code_data, ext_op_code_len - bytes_read - 1); + SAFE_BYTE_GET_AND_INC (state_machine_regs.address, + op_code_data, ext_op_code_len - bytes_read - 1, + end); state_machine_regs.op_index = 0; break; case DW_LNE_define_file: @@ -3231,8 +3285,7 @@ display_debug_lines_decoded (struct dwarf_section *section, break; case DW_LNS_fixed_advance_pc: - uladv = byte_get (data, 2); - data += 2; + SAFE_BYTE_GET_AND_INC (uladv, data, 2, end); state_machine_regs.address += uladv; state_machine_regs.op_index = 0; break; @@ -3388,12 +3441,10 @@ display_debug_pubnames (struct dwarf_section *section, data = start; - names.pn_length = byte_get (data, 4); - data += 4; + SAFE_BYTE_GET_AND_INC (names.pn_length, data, 4, end); if (names.pn_length == 0xffffffff) { - names.pn_length = byte_get (data, 8); - data += 8; + SAFE_BYTE_GET_AND_INC (names.pn_length, data, 8, end); offset_size = 8; initial_length_size = 12; } @@ -3403,11 +3454,8 @@ display_debug_pubnames (struct dwarf_section *section, initial_length_size = 4; } - names.pn_version = byte_get (data, 2); - data += 2; - - names.pn_offset = byte_get (data, offset_size); - data += offset_size; + SAFE_BYTE_GET_AND_INC (names.pn_version, data, 2, end); + SAFE_BYTE_GET_AND_INC (names.pn_offset, data, offset_size, end); if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE && num_debug_info_entries > 0 @@ -3415,8 +3463,7 @@ display_debug_pubnames (struct dwarf_section *section, 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); - names.pn_size = byte_get (data, offset_size); - data += offset_size; + SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end); start += names.pn_length + initial_length_size; @@ -3446,13 +3493,13 @@ display_debug_pubnames (struct dwarf_section *section, do { - offset = byte_get (data, offset_size); + SAFE_BYTE_GET (offset, data, offset_size, end); if (offset != 0) { data += offset_size; printf (" %-6lx\t%s\n", offset, data); - data += strlen ((char *) data) + 1; + data += strnlen ((char *) data, end - data) + 1; } } while (offset != 0); @@ -3477,7 +3524,7 @@ display_debug_macinfo (struct dwarf_section *section, while (curr < end) { unsigned int lineno; - const char *string; + const unsigned char *string; op = (enum dwarf_macinfo_record_type) *curr; curr++; @@ -3505,8 +3552,8 @@ display_debug_macinfo (struct dwarf_section *section, case DW_MACINFO_define: lineno = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; - string = (char *) curr; - curr += strlen (string) + 1; + string = curr; + curr += strnlen ((char *) string, end - string) + 1; printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"), lineno, string); break; @@ -3514,8 +3561,8 @@ display_debug_macinfo (struct dwarf_section *section, case DW_MACINFO_undef: lineno = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; - string = (char *) curr; - curr += strlen (string) + 1; + string = curr; + curr += strnlen ((char *) string, end - string) + 1; printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"), lineno, string); break; @@ -3526,8 +3573,8 @@ display_debug_macinfo (struct dwarf_section *section, constant = read_uleb128 (curr, & bytes_read, end); curr += bytes_read; - string = (char *) curr; - curr += strlen (string) + 1; + string = curr; + curr += strnlen ((char *) string, end - string) + 1; printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"), constant, string); } @@ -3562,13 +3609,12 @@ get_line_filename_and_dirname (dwarf_vma line_offset, hdrptr = section->start + line_offset; end = section->start + section->size; - length = byte_get (hdrptr, 4); - hdrptr += 4; + + SAFE_BYTE_GET_AND_INC (length, hdrptr, 4, end); if (length == 0xffffffff) { /* This section is 64-bit DWARF 3. */ - length = byte_get (hdrptr, 8); - hdrptr += 8; + SAFE_BYTE_GET_AND_INC (length, hdrptr, 8, end); offset_size = 8; initial_length_size = 12; } @@ -3579,28 +3625,29 @@ get_line_filename_and_dirname (dwarf_vma line_offset, } if (length + initial_length_size > section->size) return NULL; - version = byte_get (hdrptr, 2); - hdrptr += 2; + + SAFE_BYTE_GET_AND_INC (version, hdrptr, 2, end); if (version != 2 && version != 3 && version != 4) return NULL; hdrptr += offset_size + 1;/* Skip prologue_length and min_insn_length. */ if (version >= 4) hdrptr++; /* Skip max_ops_per_insn. */ hdrptr += 3; /* Skip default_is_stmt, line_base, line_range. */ - opcode_base = byte_get (hdrptr, 1); + + SAFE_BYTE_GET_AND_INC (opcode_base, hdrptr, 1, end); if (opcode_base == 0) return NULL; - hdrptr++; + hdrptr += opcode_base - 1; dirtable = hdrptr; /* Skip over dirname table. */ while (*hdrptr != '\0') - hdrptr += strlen ((char *) hdrptr) + 1; + hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1; hdrptr++; /* Skip the NUL at the end of the table. */ /* Now skip over preceding filename table entries. */ for (; *hdrptr != '\0' && fileidx > 1; fileidx--) { - hdrptr += strlen ((char *) hdrptr) + 1; + hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1; read_uleb128 (hdrptr, &bytes_read, end); hdrptr += bytes_read; read_uleb128 (hdrptr, &bytes_read, end); @@ -3611,12 +3658,12 @@ get_line_filename_and_dirname (dwarf_vma line_offset, if (hdrptr == end || *hdrptr == '\0') return NULL; file_name = hdrptr; - hdrptr += strlen ((char *) hdrptr) + 1; + hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1; diridx = read_uleb128 (hdrptr, &bytes_read, end); if (diridx == 0) return file_name; for (; *dirtable != '\0' && diridx > 1; diridx--) - dirtable += strlen ((char *) dirtable) + 1; + dirtable += strnlen ((char *) dirtable, end - dirtable) + 1; if (*dirtable == '\0') return NULL; *dir_name = dirtable; @@ -3642,13 +3689,11 @@ display_debug_macro (struct dwarf_section *section, { unsigned int lineno, version, flags; unsigned int offset_size = 4; - const char *string; + const unsigned char *string; dwarf_vma line_offset = 0, sec_offset = curr - start, offset; unsigned char **extended_ops = NULL; - version = byte_get (curr, 2); - curr += 2; - + SAFE_BYTE_GET_AND_INC (version, curr, 2, end); if (version != 4) { error (_("Only GNU extension to DWARF 4 of %s is currently supported.\n"), @@ -3656,7 +3701,7 @@ display_debug_macro (struct dwarf_section *section, return 0; } - flags = byte_get (curr++, 1); + SAFE_BYTE_GET_AND_INC (flags, curr, 1, end); if (flags & 1) offset_size = 8; printf (_(" Offset: 0x%lx\n"), @@ -3665,15 +3710,17 @@ display_debug_macro (struct dwarf_section *section, printf (_(" Offset size: %d\n"), offset_size); if (flags & 2) { - line_offset = byte_get (curr, offset_size); - curr += offset_size; + SAFE_BYTE_GET_AND_INC (line_offset, curr, offset_size, end); printf (_(" Offset into .debug_line: 0x%lx\n"), (unsigned long) line_offset); } if (flags & 4) { - unsigned int i, count = byte_get (curr++, 1), op; + unsigned int i, count, op; dwarf_vma nargs, n; + + SAFE_BYTE_GET_AND_INC (count, curr, 1, end); + memset (extended_op_buf, 0, sizeof (extended_op_buf)); extended_ops = extended_op_buf; if (count) @@ -3681,7 +3728,7 @@ display_debug_macro (struct dwarf_section *section, printf (_(" Extension opcode arguments:\n")); for (i = 0; i < count; i++) { - op = byte_get (curr++, 1); + SAFE_BYTE_GET_AND_INC (op, curr, 1, end); extended_ops[op] = curr; nargs = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; @@ -3692,7 +3739,9 @@ display_debug_macro (struct dwarf_section *section, printf (_(" DW_MACRO_GNU_%02x arguments: "), op); for (n = 0; n < nargs; n++) { - unsigned int form = byte_get (curr++, 1); + unsigned int form; + + SAFE_BYTE_GET_AND_INC (form, curr, 1, end); printf ("%s%s", get_FORM_name (form), n == nargs - 1 ? "\n" : ", "); switch (form) @@ -3734,7 +3783,7 @@ display_debug_macro (struct dwarf_section *section, return 0; } - op = byte_get (curr++, 1); + SAFE_BYTE_GET_AND_INC (op, curr, 1, end); if (op == 0) break; @@ -3774,8 +3823,8 @@ display_debug_macro (struct dwarf_section *section, case DW_MACRO_GNU_define: lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; - string = (char *) curr; - curr += strlen (string) + 1; + string = curr; + curr += strnlen ((char *) string, end - string) + 1; printf (_(" DW_MACRO_GNU_define - lineno : %d macro : %s\n"), lineno, string); break; @@ -3783,8 +3832,8 @@ display_debug_macro (struct dwarf_section *section, case DW_MACRO_GNU_undef: lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; - string = (char *) curr; - curr += strlen (string) + 1; + string = curr; + curr += strnlen ((char *) string, end - string) + 1; printf (_(" DW_MACRO_GNU_undef - lineno : %d macro : %s\n"), lineno, string); break; @@ -3792,8 +3841,7 @@ display_debug_macro (struct dwarf_section *section, case DW_MACRO_GNU_define_indirect: lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; - offset = byte_get (curr, offset_size); - curr += offset_size; + SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end); string = fetch_indirect_string (offset); printf (_(" DW_MACRO_GNU_define_indirect - lineno : %d macro : %s\n"), lineno, string); @@ -3802,16 +3850,14 @@ display_debug_macro (struct dwarf_section *section, case DW_MACRO_GNU_undef_indirect: lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; - offset = byte_get (curr, offset_size); - curr += offset_size; + SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end); string = fetch_indirect_string (offset); printf (_(" DW_MACRO_GNU_undef_indirect - lineno : %d macro : %s\n"), lineno, string); break; case DW_MACRO_GNU_transparent_include: - offset = byte_get (curr, offset_size); - curr += offset_size; + SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end); printf (_(" DW_MACRO_GNU_transparent_include - offset : 0x%lx\n"), (unsigned long) offset); break; @@ -3819,8 +3865,7 @@ display_debug_macro (struct dwarf_section *section, case DW_MACRO_GNU_define_indirect_alt: lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; - offset = byte_get (curr, offset_size); - curr += offset_size; + SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end); printf (_(" DW_MACRO_GNU_define_indirect_alt - lineno : %d macro offset : 0x%lx\n"), lineno, (unsigned long) offset); break; @@ -3828,15 +3873,13 @@ display_debug_macro (struct dwarf_section *section, case DW_MACRO_GNU_undef_indirect_alt: lineno = read_uleb128 (curr, &bytes_read, end); curr += bytes_read; - offset = byte_get (curr, offset_size); - curr += offset_size; + SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end); printf (_(" DW_MACRO_GNU_undef_indirect_alt - lineno : %d macro offset : 0x%lx\n"), lineno, (unsigned long) offset); break; case DW_MACRO_GNU_transparent_include_alt: - offset = byte_get (curr, offset_size); - curr += offset_size; + SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end); printf (_(" DW_MACRO_GNU_transparent_include_alt - offset : 0x%lx\n"), (unsigned long) offset); break; @@ -3862,8 +3905,11 @@ display_debug_macro (struct dwarf_section *section, printf (_(" DW_MACRO_GNU_%02x -"), op); for (n = 0; n < nargs; n++) { + int val; + + SAFE_BYTE_GET_AND_INC (val, desc, 1, end); curr - = read_and_display_attr_value (0, byte_get (desc++, 1), + = read_and_display_attr_value (0, val, curr, end, 0, 0, offset_size, version, NULL, 0, NULL, NULL); @@ -3965,10 +4011,8 @@ display_loc_list (struct dwarf_section *section, the -1 escape value. Sign extension into the top 32 bits of a 32-bit address will not affect the values that we display since we always show hex values, and always the bottom 32-bits. */ - begin = byte_get_signed (start, pointer_size); - start += pointer_size; - end = byte_get_signed (start, pointer_size); - start += pointer_size; + SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, section_end); + SAFE_BYTE_GET_AND_INC (end, start, pointer_size, section_end); if (begin == 0 && end == 0) { @@ -3993,8 +4037,7 @@ display_loc_list (struct dwarf_section *section, break; } - length = byte_get (start, 2); - start += 2; + SAFE_BYTE_GET_AND_INC (length, start, 2, section_end); if (start + length > section_end) { @@ -4076,8 +4119,7 @@ display_loc_list_dwo (struct dwarf_section *section, break; } - entry_type = byte_get (start, 1); - start++; + SAFE_BYTE_GET_AND_INC (entry_type, start, 1, section_end); switch (entry_type) { case 0: /* A terminating entry. */ @@ -4103,16 +4145,13 @@ display_loc_list_dwo (struct dwarf_section *section, idx = read_uleb128 (start, &bytes_read, section_end); start += bytes_read; print_addr_index (idx, 8); - idx = byte_get (start, 4); - start += 4; + SAFE_BYTE_GET_AND_INC (idx, start, 4, section_end); printf ("%08x ", idx); break; case 4: /* An offset pair entry. */ - idx = byte_get (start, 4); - start += 4; + SAFE_BYTE_GET_AND_INC (idx, start, 4, section_end); printf ("%08x ", idx); - idx = byte_get (start, 4); - start += 4; + SAFE_BYTE_GET_AND_INC (idx, start, 4, section_end); printf ("%08x ", idx); break; default: @@ -4128,9 +4167,7 @@ display_loc_list_dwo (struct dwarf_section *section, break; } - length = byte_get (start, 2); - start += 2; - + SAFE_BYTE_GET_AND_INC (length, start, 2, section_end); if (start + length > section_end) { warn (_("Location list starting at offset 0x%lx is not terminated.\n"), @@ -4432,13 +4469,10 @@ display_debug_aranges (struct dwarf_section *section, hdrptr = start; - arange.ar_length = byte_get (hdrptr, 4); - hdrptr += 4; - + SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 4, end); if (arange.ar_length == 0xffffffff) { - arange.ar_length = byte_get (hdrptr, 8); - hdrptr += 8; + SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 8, end); offset_size = 8; initial_length_size = 12; } @@ -4448,11 +4482,8 @@ display_debug_aranges (struct dwarf_section *section, initial_length_size = 4; } - arange.ar_version = byte_get (hdrptr, 2); - hdrptr += 2; - - arange.ar_info_offset = byte_get (hdrptr, offset_size); - hdrptr += offset_size; + SAFE_BYTE_GET_AND_INC (arange.ar_version, hdrptr, 2, end); + SAFE_BYTE_GET_AND_INC (arange.ar_info_offset, hdrptr, offset_size, end); if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE && num_debug_info_entries > 0 @@ -4460,11 +4491,8 @@ display_debug_aranges (struct dwarf_section *section, 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); - arange.ar_pointer_size = byte_get (hdrptr, 1); - hdrptr += 1; - - arange.ar_segment_size = byte_get (hdrptr, 1); - hdrptr += 1; + SAFE_BYTE_GET_AND_INC (arange.ar_pointer_size, hdrptr, 1, end); + SAFE_BYTE_GET_AND_INC (arange.ar_segment_size, hdrptr, 1, end); if (arange.ar_version != 2 && arange.ar_version != 3) { @@ -4514,13 +4542,8 @@ display_debug_aranges (struct dwarf_section *section, while (addr_ranges + 2 * address_size <= start) { - address = byte_get (addr_ranges, address_size); - - addr_ranges += address_size; - - length = byte_get (addr_ranges, address_size); - - addr_ranges += address_size; + SAFE_BYTE_GET_AND_INC (address, addr_ranges, address_size, end); + SAFE_BYTE_GET_AND_INC (length, addr_ranges, address_size, end); printf (" "); print_dwarf_vma (address, address_size); @@ -4761,12 +4784,10 @@ display_debug_ranges (struct dwarf_section *section, top 32 bits of a 32-bit address will not affect the values that we display since we always show hex values, and always the bottom 32-bits. */ - begin = byte_get_signed (start, pointer_size); - start += pointer_size; + SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish); if (start >= finish) break; - end = byte_get_signed (start, pointer_size); - start += pointer_size; + SAFE_SIGNED_BYTE_GET_AND_INC (end, start, pointer_size, finish); printf (" %8.8lx ", offset); @@ -5028,7 +5049,7 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs) printf ("\n"); } -#define GET(N) byte_get (start, N); start += N +#define GET(VAR, N) SAFE_BYTE_GET_AND_INC (VAR, start, N, end); #define LEB() read_uleb128 (start, & length_return, end); start += length_return #define SLEB() read_sleb128 (start, & length_return, end); start += length_return @@ -5066,8 +5087,8 @@ display_debug_frames (struct dwarf_section *section, int initial_length_size; saved_start = start; - length = byte_get (start, 4); start += 4; + SAFE_BYTE_GET_AND_INC (length, start, 4, end); if (length == 0) { printf ("\n%08lx ZERO terminator\n\n", @@ -5077,8 +5098,7 @@ display_debug_frames (struct dwarf_section *section, if (length == 0xffffffff) { - length = byte_get (start, 8); - start += 8; + SAFE_BYTE_GET_AND_INC (length, start, 8, end); offset_size = 8; initial_length_size = 12; } @@ -5095,7 +5115,8 @@ display_debug_frames (struct dwarf_section *section, length, (unsigned long)(saved_start - section_start)); block_end = end; } - cie_id = byte_get (start, offset_size); start += offset_size; + + SAFE_BYTE_GET_AND_INC (cie_id, start, offset_size, end); if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID)) { @@ -5122,8 +5143,8 @@ display_debug_frames (struct dwarf_section *section, if (version >= 4) { - fc->ptr_size = GET (1); - fc->segment_size = GET (1); + GET (fc->ptr_size, 1); + GET (fc->segment_size, 1); eh_addr_size = fc->ptr_size; } else @@ -5135,7 +5156,7 @@ display_debug_frames (struct dwarf_section *section, fc->data_factor = SLEB (); if (version == 1) { - fc->ra = GET (1); + GET (fc->ra, 1); } else { @@ -5263,14 +5284,17 @@ display_debug_frames (struct dwarf_section *section, segment_selector = 0; if (fc->segment_size) { - segment_selector = byte_get (start, fc->segment_size); - start += fc->segment_size; + SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end); } fc->pc_begin = get_encoded_value (start, fc->fde_encoding, section); start += encoded_ptr_size; - fc->pc_range = byte_get (start, encoded_ptr_size); - start += encoded_ptr_size; + /* 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); + if (cie->augmentation[0] == 'z') { augmentation_data_len = LEB (); @@ -5497,7 +5521,7 @@ display_debug_frames (struct dwarf_section *section, break; case DW_CFA_advance_loc1: - ofs = byte_get (start, 1); start += 1; + SAFE_BYTE_GET_AND_INC (ofs, start, 1, end); if (do_debug_frames_interp) frame_display_row (fc, &need_col_headers, &max_regs); else @@ -5508,7 +5532,7 @@ display_debug_frames (struct dwarf_section *section, break; case DW_CFA_advance_loc2: - ofs = byte_get (start, 2); start += 2; + SAFE_BYTE_GET_AND_INC (ofs, start, 2, end); if (do_debug_frames_interp) frame_display_row (fc, &need_col_headers, &max_regs); else @@ -5519,7 +5543,7 @@ display_debug_frames (struct dwarf_section *section, break; case DW_CFA_advance_loc4: - ofs = byte_get (start, 4); start += 4; + SAFE_BYTE_GET_AND_INC (ofs, start, 4, end); if (do_debug_frames_interp) frame_display_row (fc, &need_col_headers, &max_regs); else @@ -5782,7 +5806,7 @@ display_debug_frames (struct dwarf_section *section, break; case DW_CFA_MIPS_advance_loc8: - ofs = byte_get (start, 8); start += 8; + SAFE_BYTE_GET_AND_INC (ofs, start, 8, end); if (do_debug_frames_interp) frame_display_row (fc, &need_col_headers, &max_regs); else -- 2.30.2