Fix undefined arithmetic operations detected by -fsanitize=undefined when running readelf on fuzzed binaries.
PR binutils/17512 * dwarf.c (display_debug_loc): Pacify the undefined behaviour sanitizer by simplifying address difference calculation. (struct Frame_Chunk): Change type of cfa_offset to dwarf_vma in order to avoid arithmetic overflows. (frame_display_row): Cast cfa_offset before printing it. (display_debug_frames): Likewise. Check for an unexpected segment size. Chnage type of 'l' local to dwarf_vma and cast it back to an int when printing. (process_cu_tu_index): Tighten check for an invalid ncols value. * readelf.c (process_corefile_note_segment): Check for inote.descdata extending beyond the end of the section. (process_v850_notes): Likewise.
This commit is contained in:
parent
03eddd80d7
commit
c8071705c6
@ -4,6 +4,20 @@
|
|||||||
* resrc.c (write_rc_messagetable): Tighten check for invalid
|
* resrc.c (write_rc_messagetable): Tighten check for invalid
|
||||||
message lengths.
|
message lengths.
|
||||||
|
|
||||||
|
* dwarf.c (display_debug_loc): Pacify the undefined behaviour
|
||||||
|
sanitizer by simplifying address difference calculation.
|
||||||
|
(struct Frame_Chunk): Change type of cfa_offset to dwarf_vma in
|
||||||
|
order to avoid arithmetic overflows.
|
||||||
|
(frame_display_row): Cast cfa_offset before printing it.
|
||||||
|
(display_debug_frames): Likewise.
|
||||||
|
Check for an unexpected segment size.
|
||||||
|
Chnage type of 'l' local to dwarf_vma and cast it back to an int
|
||||||
|
when printing.
|
||||||
|
(process_cu_tu_index): Tighten check for an invalid ncols value.
|
||||||
|
* readelf.c (process_corefile_note_segment): Check for
|
||||||
|
inote.descdata extending beyond the end of the section.
|
||||||
|
(process_v850_notes): Likewise.
|
||||||
|
|
||||||
2015-02-26 Terry Guo <terry.guo@arm.com>
|
2015-02-26 Terry Guo <terry.guo@arm.com>
|
||||||
|
|
||||||
* readelf.c (arm_attr_tag_ABI_HardFP_use): Update how we
|
* readelf.c (arm_attr_tag_ABI_HardFP_use): Update how we
|
||||||
|
@ -4719,11 +4719,11 @@ display_debug_loc (struct dwarf_section *section, void *file)
|
|||||||
if (start < next)
|
if (start < next)
|
||||||
warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
|
warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
|
||||||
(unsigned long) (start - section_begin),
|
(unsigned long) (start - section_begin),
|
||||||
(unsigned long) (next - section_begin));
|
(unsigned long) offset);
|
||||||
else if (start > next)
|
else if (start > next)
|
||||||
warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_loc section.\n"),
|
warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_loc section.\n"),
|
||||||
(unsigned long) (start - section_begin),
|
(unsigned long) (start - section_begin),
|
||||||
(unsigned long) (next - section_begin));
|
(unsigned long) offset);
|
||||||
}
|
}
|
||||||
start = next;
|
start = next;
|
||||||
|
|
||||||
@ -5244,7 +5244,7 @@ typedef struct Frame_Chunk
|
|||||||
dwarf_vma pc_begin;
|
dwarf_vma pc_begin;
|
||||||
dwarf_vma pc_range;
|
dwarf_vma pc_range;
|
||||||
int cfa_reg;
|
int cfa_reg;
|
||||||
int cfa_offset;
|
dwarf_vma cfa_offset;
|
||||||
unsigned int ra;
|
unsigned int ra;
|
||||||
unsigned char fde_encoding;
|
unsigned char fde_encoding;
|
||||||
unsigned char cfa_exp;
|
unsigned char cfa_exp;
|
||||||
@ -5481,7 +5481,7 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_reg
|
|||||||
if (fc->cfa_exp)
|
if (fc->cfa_exp)
|
||||||
strcpy (tmp, "exp");
|
strcpy (tmp, "exp");
|
||||||
else
|
else
|
||||||
sprintf (tmp, "%s%+d", regname (fc->cfa_reg, 1), fc->cfa_offset);
|
sprintf (tmp, "%s%+d", regname (fc->cfa_reg, 1), (int) fc->cfa_offset);
|
||||||
printf ("%-8s ", tmp);
|
printf ("%-8s ", tmp);
|
||||||
|
|
||||||
for (r = 0; r < fc->ncols; r++)
|
for (r = 0; r < fc->ncols; r++)
|
||||||
@ -5921,7 +5921,15 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
|
|
||||||
segment_selector = 0;
|
segment_selector = 0;
|
||||||
if (fc->segment_size)
|
if (fc->segment_size)
|
||||||
SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
|
{
|
||||||
|
if (fc->segment_size > sizeof (segment_selector))
|
||||||
|
{
|
||||||
|
/* PR 17512: file: 9e196b3e. */
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section, end);
|
fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section, end);
|
||||||
|
|
||||||
@ -6123,7 +6131,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
unsigned char * tmp;
|
unsigned char * tmp;
|
||||||
unsigned op, opa;
|
unsigned op, opa;
|
||||||
unsigned long ul, reg, roffs;
|
unsigned long ul, reg, roffs;
|
||||||
long l;
|
dwarf_vma l;
|
||||||
dwarf_vma ofs;
|
dwarf_vma ofs;
|
||||||
dwarf_vma vma;
|
dwarf_vma vma;
|
||||||
const char *reg_prefix = "";
|
const char *reg_prefix = "";
|
||||||
@ -6375,7 +6383,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
fc->cfa_exp = 0;
|
fc->cfa_exp = 0;
|
||||||
if (! do_debug_frames_interp)
|
if (! do_debug_frames_interp)
|
||||||
printf (" DW_CFA_def_cfa: %s ofs %d\n",
|
printf (" DW_CFA_def_cfa: %s ofs %d\n",
|
||||||
regname (fc->cfa_reg, 0), fc->cfa_offset);
|
regname (fc->cfa_reg, 0), (int) fc->cfa_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa_register:
|
case DW_CFA_def_cfa_register:
|
||||||
@ -6389,7 +6397,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
case DW_CFA_def_cfa_offset:
|
case DW_CFA_def_cfa_offset:
|
||||||
fc->cfa_offset = LEB ();
|
fc->cfa_offset = LEB ();
|
||||||
if (! do_debug_frames_interp)
|
if (! do_debug_frames_interp)
|
||||||
printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
|
printf (" DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_nop:
|
case DW_CFA_nop:
|
||||||
@ -6473,7 +6481,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||||
printf (" DW_CFA_offset_extended_sf: %s%s at cfa%+ld\n",
|
printf (" DW_CFA_offset_extended_sf: %s%s at cfa%+ld\n",
|
||||||
reg_prefix, regname (reg, 0),
|
reg_prefix, regname (reg, 0),
|
||||||
l * fc->data_factor);
|
(long)(l * fc->data_factor));
|
||||||
if (*reg_prefix == '\0')
|
if (*reg_prefix == '\0')
|
||||||
{
|
{
|
||||||
fc->col_type[reg] = DW_CFA_offset;
|
fc->col_type[reg] = DW_CFA_offset;
|
||||||
@ -6489,7 +6497,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||||
printf (" DW_CFA_val_offset_sf: %s%s at cfa%+ld\n",
|
printf (" DW_CFA_val_offset_sf: %s%s at cfa%+ld\n",
|
||||||
reg_prefix, regname (reg, 0),
|
reg_prefix, regname (reg, 0),
|
||||||
l * fc->data_factor);
|
(long)(l * fc->data_factor));
|
||||||
if (*reg_prefix == '\0')
|
if (*reg_prefix == '\0')
|
||||||
{
|
{
|
||||||
fc->col_type[reg] = DW_CFA_val_offset;
|
fc->col_type[reg] = DW_CFA_val_offset;
|
||||||
@ -6504,14 +6512,14 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
fc->cfa_exp = 0;
|
fc->cfa_exp = 0;
|
||||||
if (! do_debug_frames_interp)
|
if (! do_debug_frames_interp)
|
||||||
printf (" DW_CFA_def_cfa_sf: %s ofs %d\n",
|
printf (" DW_CFA_def_cfa_sf: %s ofs %d\n",
|
||||||
regname (fc->cfa_reg, 0), fc->cfa_offset);
|
regname (fc->cfa_reg, 0), (int) fc->cfa_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_def_cfa_offset_sf:
|
case DW_CFA_def_cfa_offset_sf:
|
||||||
fc->cfa_offset = SLEB ();
|
fc->cfa_offset = SLEB ();
|
||||||
fc->cfa_offset = fc->cfa_offset * fc->data_factor;
|
fc->cfa_offset *= fc->data_factor;
|
||||||
if (! do_debug_frames_interp)
|
if (! do_debug_frames_interp)
|
||||||
printf (" DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
|
printf (" DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_MIPS_advance_loc8:
|
case DW_CFA_MIPS_advance_loc8:
|
||||||
@ -6546,7 +6554,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||||
printf (" DW_CFA_GNU_negative_offset_extended: %s%s at cfa%+ld\n",
|
printf (" DW_CFA_GNU_negative_offset_extended: %s%s at cfa%+ld\n",
|
||||||
reg_prefix, regname (reg, 0),
|
reg_prefix, regname (reg, 0),
|
||||||
l * fc->data_factor);
|
(long)(l * fc->data_factor));
|
||||||
if (*reg_prefix == '\0')
|
if (*reg_prefix == '\0')
|
||||||
{
|
{
|
||||||
fc->col_type[reg] = DW_CFA_offset;
|
fc->col_type[reg] = DW_CFA_offset;
|
||||||
@ -7026,7 +7034,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
|
|||||||
|
|
||||||
/* PR 17531: file: 0dd159bf.
|
/* PR 17531: file: 0dd159bf.
|
||||||
Check for wraparound with an overlarge ncols value. */
|
Check for wraparound with an overlarge ncols value. */
|
||||||
if ((unsigned int) ((poffsets - ppool) / 4) != ncols)
|
if (poffsets < ppool || (unsigned int) ((poffsets - ppool) / 4) != ncols)
|
||||||
{
|
{
|
||||||
warn (_("Overlarge number of columns: %x\n"), ncols);
|
warn (_("Overlarge number of columns: %x\n"), ncols);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -15205,6 +15205,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
{
|
{
|
||||||
Elf_External_Note * pnotes;
|
Elf_External_Note * pnotes;
|
||||||
Elf_External_Note * external;
|
Elf_External_Note * external;
|
||||||
|
char * end;
|
||||||
int res = 1;
|
int res = 1;
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
@ -15221,13 +15222,14 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
(unsigned long) offset, (unsigned long) length);
|
(unsigned long) offset, (unsigned long) length);
|
||||||
printf (_(" %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
|
printf (_(" %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
|
||||||
|
|
||||||
while ((char *) external < (char *) pnotes + length)
|
end = (char *) pnotes + length;
|
||||||
|
while ((char *) external < end)
|
||||||
{
|
{
|
||||||
Elf_Internal_Note inote;
|
Elf_Internal_Note inote;
|
||||||
size_t min_notesz;
|
size_t min_notesz;
|
||||||
char *next;
|
char *next;
|
||||||
char * temp = NULL;
|
char * temp = NULL;
|
||||||
size_t data_remaining = ((char *) pnotes + length) - (char *) external;
|
size_t data_remaining = end - (char *) external;
|
||||||
|
|
||||||
if (!is_ia64_vms ())
|
if (!is_ia64_vms ())
|
||||||
{
|
{
|
||||||
@ -15246,12 +15248,13 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
inote.descsz = BYTE_GET (external->descsz);
|
inote.descsz = BYTE_GET (external->descsz);
|
||||||
inote.descdata = inote.namedata + align_power (inote.namesz, 2);
|
inote.descdata = inote.namedata + align_power (inote.namesz, 2);
|
||||||
/* PR 17531: file: 3443835e. */
|
/* PR 17531: file: 3443835e. */
|
||||||
if (inote.descdata < (char *) pnotes)
|
if (inote.descdata < (char *) pnotes || inote.descdata > end)
|
||||||
{
|
{
|
||||||
warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
|
warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
|
||||||
inote.descdata = inote.namedata;
|
inote.descdata = inote.namedata;
|
||||||
inote.namesz = 0;
|
inote.namesz = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inote.descpos = offset + (inote.descdata - (char *) pnotes);
|
inote.descpos = offset + (inote.descdata - (char *) pnotes);
|
||||||
next = inote.descdata + align_power (inote.descsz, 2);
|
next = inote.descdata + align_power (inote.descsz, 2);
|
||||||
}
|
}
|
||||||
@ -15358,6 +15361,7 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
{
|
{
|
||||||
Elf_External_Note * pnotes;
|
Elf_External_Note * pnotes;
|
||||||
Elf_External_Note * external;
|
Elf_External_Note * external;
|
||||||
|
char * end;
|
||||||
int res = 1;
|
int res = 1;
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
@ -15369,11 +15373,12 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
external = pnotes;
|
external = pnotes;
|
||||||
|
end = (char*) pnotes + length;
|
||||||
|
|
||||||
printf (_("\nDisplaying contents of Renesas V850 notes section at offset 0x%lx with length 0x%lx:\n"),
|
printf (_("\nDisplaying contents of Renesas V850 notes section at offset 0x%lx with length 0x%lx:\n"),
|
||||||
(unsigned long) offset, (unsigned long) length);
|
(unsigned long) offset, (unsigned long) length);
|
||||||
|
|
||||||
while (external < (Elf_External_Note *) ((char *) pnotes + length))
|
while ((char *) external + sizeof (Elf_External_Note) < end)
|
||||||
{
|
{
|
||||||
Elf_External_Note * next;
|
Elf_External_Note * next;
|
||||||
Elf_Internal_Note inote;
|
Elf_Internal_Note inote;
|
||||||
@ -15385,9 +15390,16 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
inote.descdata = inote.namedata + align_power (inote.namesz, 2);
|
inote.descdata = inote.namedata + align_power (inote.namesz, 2);
|
||||||
inote.descpos = offset + (inote.descdata - (char *) pnotes);
|
inote.descpos = offset + (inote.descdata - (char *) pnotes);
|
||||||
|
|
||||||
|
if (inote.descdata < (char *) pnotes || inote.descdata >= end)
|
||||||
|
{
|
||||||
|
warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
|
||||||
|
inote.descdata = inote.namedata;
|
||||||
|
inote.namesz = 0;
|
||||||
|
}
|
||||||
|
|
||||||
next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
|
next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
|
||||||
|
|
||||||
if ( ((char *) next > ((char *) pnotes) + length)
|
if ( ((char *) next > end)
|
||||||
|| ((char *) next < (char *) pnotes))
|
|| ((char *) next < (char *) pnotes))
|
||||||
{
|
{
|
||||||
warn (_("corrupt descsz found in note at offset 0x%lx\n"),
|
warn (_("corrupt descsz found in note at offset 0x%lx\n"),
|
||||||
@ -15400,7 +15412,7 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
external = next;
|
external = next;
|
||||||
|
|
||||||
/* Prevent out-of-bounds indexing. */
|
/* Prevent out-of-bounds indexing. */
|
||||||
if ( inote.namedata + inote.namesz > (char *) pnotes + length
|
if ( inote.namedata + inote.namesz > end
|
||||||
|| inote.namedata + inote.namesz < inote.namedata)
|
|| inote.namedata + inote.namesz < inote.namedata)
|
||||||
{
|
{
|
||||||
warn (_("corrupt namesz found in note at offset 0x%lx\n"),
|
warn (_("corrupt namesz found in note at offset 0x%lx\n"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user