Fix address violation when reading corrupt DWARF data.
PR binutils/21648 * dwarf.c (LEB): Rename to SKIP_ULEB and READ_ULEB. Add check for reading a value that is too big for the containing variable. (SLEB): Rename to SKIP_SLEB and READ_SLEB. Add similar check. Replace uses of LEB and SLEB with appropriate new macro. (display_debug_frames): Use an unsigned int for the 'reg' variable. Use a signed long for the 'l' variable.
This commit is contained in:
parent
2c6b98ea6f
commit
7f2c8a1d37
2 changed files with 106 additions and 58 deletions
|
@ -1,3 +1,13 @@
|
|||
2017-06-21 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/21648
|
||||
* dwarf.c (LEB): Rename to SKIP_ULEB and READ_ULEB. Add check for
|
||||
reading a value that is too big for the containing variable.
|
||||
(SLEB): Rename to SKIP_SLEB and READ_SLEB. Add similar check.
|
||||
Replace uses of LEB and SLEB with appropriate new macro.
|
||||
(display_debug_frames): Use an unsigned int for the 'reg'
|
||||
variable. Use a signed long for the 'l' variable.
|
||||
|
||||
2017-06-19 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/21619
|
||||
|
|
154
binutils/dwarf.c
154
binutils/dwarf.c
|
@ -313,6 +313,35 @@ read_uleb128 (unsigned char * data,
|
|||
return read_leb128 (data, length_return, FALSE, end);
|
||||
}
|
||||
|
||||
#define SKIP_ULEB() read_uleb128 (start, & length_return, end); start += length_return
|
||||
#define SKIP_SLEB() read_sleb128 (start, & length_return, end); start += length_return
|
||||
|
||||
#define READ_ULEB(var) \
|
||||
do \
|
||||
{ \
|
||||
dwarf_vma _val; \
|
||||
\
|
||||
(var) = _val = read_uleb128 (start, &length_return, end); \
|
||||
if ((var) != _val) \
|
||||
error (_("Internal error: %s%d: LEB value (%#lx) too large for containing variable\n"), \
|
||||
__FILE__, __LINE__, _val); \
|
||||
start += length_return; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define READ_SLEB(var) \
|
||||
do \
|
||||
{ \
|
||||
dwarf_signed_vma _val; \
|
||||
\
|
||||
(var) = _val = read_sleb128 (start, &length_return, end); \
|
||||
if ((var) != _val) \
|
||||
error (_("Internal error: %s%d: LEB value (%#lx) too large for containing variable\n"), \
|
||||
__FILE__, __LINE__, _val); \
|
||||
start += length_return; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define SAFE_BYTE_GET(VAL, PTR, AMOUNT, END) \
|
||||
do \
|
||||
{ \
|
||||
|
@ -6421,6 +6450,7 @@ static const char *
|
|||
regname (unsigned int regno, int row)
|
||||
{
|
||||
static char reg[64];
|
||||
|
||||
if (dwarf_regnames
|
||||
&& regno < dwarf_regnames_count
|
||||
&& dwarf_regnames [regno] != NULL)
|
||||
|
@ -6509,8 +6539,6 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_reg
|
|||
}
|
||||
|
||||
#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
|
||||
|
||||
static unsigned char *
|
||||
read_cie (unsigned char *start, unsigned char *end,
|
||||
|
@ -6575,26 +6603,27 @@ read_cie (unsigned char *start, unsigned char *end,
|
|||
fc->ptr_size = eh_addr_size;
|
||||
fc->segment_size = 0;
|
||||
}
|
||||
fc->code_factor = LEB ();
|
||||
fc->data_factor = SLEB ();
|
||||
READ_ULEB (fc->code_factor);
|
||||
READ_SLEB (fc->data_factor);
|
||||
if (version == 1)
|
||||
{
|
||||
GET (fc->ra, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fc->ra = LEB ();
|
||||
READ_ULEB (fc->ra);
|
||||
}
|
||||
|
||||
if (fc->augmentation[0] == 'z')
|
||||
{
|
||||
augmentation_data_len = LEB ();
|
||||
READ_ULEB (augmentation_data_len);
|
||||
augmentation_data = start;
|
||||
start += augmentation_data_len;
|
||||
/* PR 17512: file: 11042-2589-0.004. */
|
||||
if (start > end)
|
||||
{
|
||||
warn (_("Augmentation data too long: 0x%lx\n"), augmentation_data_len);
|
||||
warn (_("Augmentation data too long: %#lx, expected at most %#lx\n"),
|
||||
augmentation_data_len, (long)((end - start) + augmentation_data_len));
|
||||
return end;
|
||||
}
|
||||
}
|
||||
|
@ -6929,7 +6958,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
|
||||
if (cie->augmentation[0] == 'z')
|
||||
{
|
||||
augmentation_data_len = LEB ();
|
||||
READ_ULEB (augmentation_data_len);
|
||||
augmentation_data = start;
|
||||
start += augmentation_data_len;
|
||||
/* PR 17512: file: 722-8446-0.004. */
|
||||
|
@ -6999,7 +7028,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
case DW_CFA_advance_loc:
|
||||
break;
|
||||
case DW_CFA_offset:
|
||||
LEB ();
|
||||
SKIP_ULEB ();
|
||||
if (frame_need_space (fc, opa) >= 0)
|
||||
fc->col_type[opa] = DW_CFA_undefined;
|
||||
break;
|
||||
|
@ -7021,41 +7050,44 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
case DW_CFA_offset_extended:
|
||||
case DW_CFA_val_offset:
|
||||
reg = LEB (); LEB ();
|
||||
READ_ULEB (reg);
|
||||
SKIP_ULEB ();
|
||||
if (frame_need_space (fc, reg) >= 0)
|
||||
fc->col_type[reg] = DW_CFA_undefined;
|
||||
break;
|
||||
case DW_CFA_restore_extended:
|
||||
reg = LEB ();
|
||||
READ_ULEB (reg);
|
||||
if (frame_need_space (fc, reg) >= 0)
|
||||
fc->col_type[reg] = DW_CFA_undefined;
|
||||
break;
|
||||
case DW_CFA_undefined:
|
||||
reg = LEB ();
|
||||
READ_ULEB (reg);
|
||||
if (frame_need_space (fc, reg) >= 0)
|
||||
fc->col_type[reg] = DW_CFA_undefined;
|
||||
break;
|
||||
case DW_CFA_same_value:
|
||||
reg = LEB ();
|
||||
READ_ULEB (reg);
|
||||
if (frame_need_space (fc, reg) >= 0)
|
||||
fc->col_type[reg] = DW_CFA_undefined;
|
||||
break;
|
||||
case DW_CFA_register:
|
||||
reg = LEB (); LEB ();
|
||||
READ_ULEB (reg);
|
||||
SKIP_ULEB ();
|
||||
if (frame_need_space (fc, reg) >= 0)
|
||||
fc->col_type[reg] = DW_CFA_undefined;
|
||||
break;
|
||||
case DW_CFA_def_cfa:
|
||||
LEB (); LEB ();
|
||||
SKIP_ULEB ();
|
||||
SKIP_ULEB ();
|
||||
break;
|
||||
case DW_CFA_def_cfa_register:
|
||||
LEB ();
|
||||
SKIP_ULEB ();
|
||||
break;
|
||||
case DW_CFA_def_cfa_offset:
|
||||
LEB ();
|
||||
SKIP_ULEB ();
|
||||
break;
|
||||
case DW_CFA_def_cfa_expression:
|
||||
temp = LEB ();
|
||||
READ_ULEB (temp);
|
||||
new_start = start + temp;
|
||||
if (new_start < start)
|
||||
{
|
||||
|
@ -7067,8 +7099,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
case DW_CFA_expression:
|
||||
case DW_CFA_val_expression:
|
||||
reg = LEB ();
|
||||
temp = LEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_ULEB (temp);
|
||||
new_start = start + temp;
|
||||
if (new_start < start)
|
||||
{
|
||||
|
@ -7083,24 +7115,27 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
case DW_CFA_offset_extended_sf:
|
||||
case DW_CFA_val_offset_sf:
|
||||
reg = LEB (); SLEB ();
|
||||
READ_ULEB (reg);
|
||||
SKIP_SLEB ();
|
||||
if (frame_need_space (fc, reg) >= 0)
|
||||
fc->col_type[reg] = DW_CFA_undefined;
|
||||
break;
|
||||
case DW_CFA_def_cfa_sf:
|
||||
LEB (); SLEB ();
|
||||
SKIP_ULEB ();
|
||||
SKIP_SLEB ();
|
||||
break;
|
||||
case DW_CFA_def_cfa_offset_sf:
|
||||
SLEB ();
|
||||
SKIP_SLEB ();
|
||||
break;
|
||||
case DW_CFA_MIPS_advance_loc8:
|
||||
start += 8;
|
||||
break;
|
||||
case DW_CFA_GNU_args_size:
|
||||
LEB ();
|
||||
SKIP_ULEB ();
|
||||
break;
|
||||
case DW_CFA_GNU_negative_offset_extended:
|
||||
reg = LEB (); LEB ();
|
||||
READ_ULEB (reg);
|
||||
SKIP_ULEB ();
|
||||
if (frame_need_space (fc, reg) >= 0)
|
||||
fc->col_type[reg] = DW_CFA_undefined;
|
||||
break;
|
||||
|
@ -7120,8 +7155,12 @@ display_debug_frames (struct dwarf_section *section,
|
|||
{
|
||||
unsigned char * tmp;
|
||||
unsigned op, opa;
|
||||
unsigned long ul, reg, roffs;
|
||||
dwarf_vma l;
|
||||
unsigned long ul, roffs;
|
||||
/* Note: It is tempting to use an unsigned long for 'reg' but there
|
||||
are various functions, notably frame_space_needed() that assume that
|
||||
reg is an unsigned int. */
|
||||
unsigned int reg;
|
||||
dwarf_signed_vma l;
|
||||
dwarf_vma ofs;
|
||||
dwarf_vma vma;
|
||||
const char *reg_prefix = "";
|
||||
|
@ -7152,7 +7191,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_offset:
|
||||
roffs = LEB ();
|
||||
READ_ULEB (roffs);
|
||||
if (opa >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7239,8 +7278,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_offset_extended:
|
||||
reg = LEB ();
|
||||
roffs = LEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_ULEB (roffs);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7255,8 +7294,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_val_offset:
|
||||
reg = LEB ();
|
||||
roffs = LEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_ULEB (roffs);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7271,7 +7310,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_restore_extended:
|
||||
reg = LEB ();
|
||||
READ_ULEB (reg);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7293,7 +7332,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_undefined:
|
||||
reg = LEB ();
|
||||
READ_ULEB (reg);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7307,7 +7346,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_same_value:
|
||||
reg = LEB ();
|
||||
READ_ULEB (reg);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7321,8 +7360,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_register:
|
||||
reg = LEB ();
|
||||
roffs = LEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_ULEB (roffs);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7385,8 +7424,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_def_cfa:
|
||||
fc->cfa_reg = LEB ();
|
||||
fc->cfa_offset = LEB ();
|
||||
READ_SLEB (fc->cfa_reg);
|
||||
READ_ULEB (fc->cfa_offset);
|
||||
fc->cfa_exp = 0;
|
||||
if (! do_debug_frames_interp)
|
||||
printf (" DW_CFA_def_cfa: %s ofs %d\n",
|
||||
|
@ -7394,7 +7433,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_def_cfa_register:
|
||||
fc->cfa_reg = LEB ();
|
||||
READ_SLEB (fc->cfa_reg);
|
||||
fc->cfa_exp = 0;
|
||||
if (! do_debug_frames_interp)
|
||||
printf (" DW_CFA_def_cfa_register: %s\n",
|
||||
|
@ -7402,7 +7441,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_def_cfa_offset:
|
||||
fc->cfa_offset = LEB ();
|
||||
READ_ULEB (fc->cfa_offset);
|
||||
if (! do_debug_frames_interp)
|
||||
printf (" DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
|
||||
break;
|
||||
|
@ -7413,7 +7452,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_def_cfa_expression:
|
||||
ul = LEB ();
|
||||
READ_ULEB (ul);
|
||||
if (start >= block_end || ul > (unsigned long) (block_end - start))
|
||||
{
|
||||
printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
|
||||
|
@ -7431,8 +7470,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_expression:
|
||||
reg = LEB ();
|
||||
ul = LEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_ULEB (ul);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
/* PR 17512: file: 069-133014-0.006. */
|
||||
|
@ -7457,8 +7496,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_val_expression:
|
||||
reg = LEB ();
|
||||
ul = LEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_ULEB (ul);
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
tmp = start + ul;
|
||||
|
@ -7481,8 +7520,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_offset_extended_sf:
|
||||
reg = LEB ();
|
||||
l = SLEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_SLEB (l);
|
||||
if (frame_need_space (fc, reg) < 0)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7497,8 +7536,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_val_offset_sf:
|
||||
reg = LEB ();
|
||||
l = SLEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_SLEB (l);
|
||||
if (frame_need_space (fc, reg) < 0)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7513,8 +7552,8 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_def_cfa_sf:
|
||||
fc->cfa_reg = LEB ();
|
||||
fc->cfa_offset = SLEB ();
|
||||
READ_SLEB (fc->cfa_reg);
|
||||
READ_ULEB (fc->cfa_offset);
|
||||
fc->cfa_offset = fc->cfa_offset * fc->data_factor;
|
||||
fc->cfa_exp = 0;
|
||||
if (! do_debug_frames_interp)
|
||||
|
@ -7523,7 +7562,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_def_cfa_offset_sf:
|
||||
fc->cfa_offset = SLEB ();
|
||||
READ_ULEB (fc->cfa_offset);
|
||||
fc->cfa_offset *= fc->data_factor;
|
||||
if (! do_debug_frames_interp)
|
||||
printf (" DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
|
||||
|
@ -7548,14 +7587,15 @@ display_debug_frames (struct dwarf_section *section,
|
|||
break;
|
||||
|
||||
case DW_CFA_GNU_args_size:
|
||||
ul = LEB ();
|
||||
READ_ULEB (ul);
|
||||
if (! do_debug_frames_interp)
|
||||
printf (" DW_CFA_GNU_args_size: %ld\n", ul);
|
||||
break;
|
||||
|
||||
case DW_CFA_GNU_negative_offset_extended:
|
||||
reg = LEB ();
|
||||
l = - LEB ();
|
||||
READ_ULEB (reg);
|
||||
READ_SLEB (l);
|
||||
l = - l;
|
||||
if (frame_need_space (fc, reg) < 0)
|
||||
reg_prefix = bad_reg;
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -7592,8 +7632,6 @@ display_debug_frames (struct dwarf_section *section,
|
|||
}
|
||||
|
||||
#undef GET
|
||||
#undef LEB
|
||||
#undef SLEB
|
||||
|
||||
static int
|
||||
display_gdb_index (struct dwarf_section *section,
|
||||
|
|
Loading…
Add table
Reference in a new issue