mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 10:35:12 +08:00
Fix seg-fault in readelf when decoding corrupt IA64 unwind information.
PR binutils/18420 * ia64-unwind.c (unw_decode): Add end parameter. Pass parameter on to decode functions. (unw_devode_p2_p5): Pass end paraemter to UNW_DEC_SPILL_MASK. (UNW_DEC_SPILL_MASK): Add end parameter. Check that unw_rlen does not take us beyond the end of the buffer. * ia64-unwind.h (unw_decode): Update prototype. * readelf.c (dump_ia64_unwind): Pass end pointer to unw_decode.
This commit is contained in:
parent
35d7c4317b
commit
b4477bc818
@ -1,3 +1,14 @@
|
|||||||
|
2015-05-18 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/18420
|
||||||
|
* ia64-unwind.c (unw_decode): Add end parameter. Pass parameter
|
||||||
|
on to decode functions.
|
||||||
|
(unw_devode_p2_p5): Pass end paraemter to UNW_DEC_SPILL_MASK.
|
||||||
|
(UNW_DEC_SPILL_MASK): Add end parameter. Check that unw_rlen does
|
||||||
|
not take us beyond the end of the buffer.
|
||||||
|
* ia64-unwind.h (unw_decode): Update prototype.
|
||||||
|
* readelf.c (dump_ia64_unwind): Pass end pointer to unw_decode.
|
||||||
|
|
||||||
2015-05-15 H.J. Lu <hongjiu.lu@intel.com>
|
2015-05-15 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* readelf.c (dump_section_as_strings): Change pointers from
|
* readelf.c (dump_section_as_strings): Change pointers from
|
||||||
|
@ -6735,7 +6735,7 @@ dump_ia64_unwind (struct ia64_unw_aux_info * aux)
|
|||||||
if (end > aux->info + aux->info_size)
|
if (end > aux->info + aux->info_size)
|
||||||
end = aux->info + aux->info_size;
|
end = aux->info + aux->info_size;
|
||||||
for (dp = head + 8; dp < end;)
|
for (dp = head + 8; dp < end;)
|
||||||
dp = unw_decode (dp, in_body, & in_body);
|
dp = unw_decode (dp, in_body, & in_body, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (aux->funtab);
|
free (aux->funtab);
|
||||||
|
@ -349,14 +349,22 @@ typedef bfd_vma unw_word;
|
|||||||
printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \
|
printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \
|
||||||
fmt, 4*(unsigned long)pspoff)
|
fmt, 4*(unsigned long)pspoff)
|
||||||
|
|
||||||
#define UNW_DEC_SPILL_MASK(fmt, dp, arg) \
|
#define UNW_DEC_SPILL_MASK(fmt, dp, arg, end) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
static const char *spill_type = "-frb"; \
|
static const char *spill_type = "-frb"; \
|
||||||
unsigned const char *imaskp = dp; \
|
unsigned const char *imaskp = dp; \
|
||||||
unsigned char mask = 0; \
|
unsigned char mask = 0; \
|
||||||
bfd_vma insn = 0; \
|
bfd_vma insn = 0; \
|
||||||
\
|
\
|
||||||
|
/* PR 18420. */ \
|
||||||
|
if ((dp + (unw_rlen / 4)) > end) \
|
||||||
|
{ \
|
||||||
|
printf ("\nERROR: unwind length too long (0x%lx > 0x%lx)\n\n",\
|
||||||
|
(long) (unw_rlen / 4), (long)(end - dp)); \
|
||||||
|
/* FIXME: Should we reset unw_rlen ? */ \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
printf ("\t%s:spill_mask(imask=[", fmt); \
|
printf ("\t%s:spill_mask(imask=[", fmt); \
|
||||||
for (insn = 0; insn < unw_rlen; ++insn) \
|
for (insn = 0; insn < unw_rlen; ++insn) \
|
||||||
{ \
|
{ \
|
||||||
@ -533,36 +541,6 @@ typedef bfd_vma unw_word;
|
|||||||
* UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
|
* UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static unw_word unw_decode_uleb128 (const unsigned char **);
|
|
||||||
static const unsigned char *unw_decode_x1
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_x2
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_x3
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_x4
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_r1
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_r2
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_r3
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_p1
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_p2_p5
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_p6
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_p7_p10
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_b1
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_b2
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
static const unsigned char *unw_decode_b3_x4
|
|
||||||
(const unsigned char *, unsigned int, void *);
|
|
||||||
|
|
||||||
static unw_word
|
static unw_word
|
||||||
unw_decode_uleb128 (const unsigned char **dpp)
|
unw_decode_uleb128 (const unsigned char **dpp)
|
||||||
{
|
{
|
||||||
@ -671,7 +649,8 @@ unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
|
unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
int body = (code & 0x20) != 0;
|
int body = (code & 0x20) != 0;
|
||||||
unw_word rlen;
|
unw_word rlen;
|
||||||
@ -682,7 +661,8 @@ unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg)
|
unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unsigned char byte1, mask, grsave;
|
unsigned char byte1, mask, grsave;
|
||||||
unw_word rlen;
|
unw_word rlen;
|
||||||
@ -697,7 +677,8 @@ unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg)
|
unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unw_word rlen;
|
unw_word rlen;
|
||||||
|
|
||||||
@ -708,7 +689,8 @@ unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg)
|
|||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_p1 (const unsigned char *dp, unsigned int code,
|
unw_decode_p1 (const unsigned char *dp, unsigned int code,
|
||||||
void *arg ATTRIBUTE_UNUSED)
|
void *arg ATTRIBUTE_UNUSED,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unsigned char brmask = (code & 0x1f);
|
unsigned char brmask = (code & 0x1f);
|
||||||
|
|
||||||
@ -718,7 +700,8 @@ unw_decode_p1 (const unsigned char *dp, unsigned int code,
|
|||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
|
unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
|
||||||
void *arg ATTRIBUTE_UNUSED)
|
void *arg ATTRIBUTE_UNUSED,
|
||||||
|
const unsigned char * end)
|
||||||
{
|
{
|
||||||
if ((code & 0x10) == 0)
|
if ((code & 0x10) == 0)
|
||||||
{
|
{
|
||||||
@ -777,7 +760,7 @@ unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((code & 0x7) == 0)
|
else if ((code & 0x7) == 0)
|
||||||
UNW_DEC_SPILL_MASK ("P4", dp, arg);
|
UNW_DEC_SPILL_MASK ("P4", dp, arg, end);
|
||||||
else if ((code & 0x7) == 1)
|
else if ((code & 0x7) == 1)
|
||||||
{
|
{
|
||||||
unw_word grmask, frmask, byte1, byte2, byte3;
|
unw_word grmask, frmask, byte1, byte2, byte3;
|
||||||
@ -797,7 +780,8 @@ unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
|
|||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_p6 (const unsigned char *dp, unsigned int code,
|
unw_decode_p6 (const unsigned char *dp, unsigned int code,
|
||||||
void *arg ATTRIBUTE_UNUSED)
|
void *arg ATTRIBUTE_UNUSED,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
int gregs = (code & 0x10) != 0;
|
int gregs = (code & 0x10) != 0;
|
||||||
unsigned char mask = (code & 0x0f);
|
unsigned char mask = (code & 0x0f);
|
||||||
@ -810,7 +794,8 @@ unw_decode_p6 (const unsigned char *dp, unsigned int code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
|
unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unsigned char r, byte1, byte2;
|
unsigned char r, byte1, byte2;
|
||||||
unw_word t, size;
|
unw_word t, size;
|
||||||
@ -984,7 +969,8 @@ unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
|
|||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_b1 (const unsigned char *dp, unsigned int code,
|
unw_decode_b1 (const unsigned char *dp, unsigned int code,
|
||||||
void *arg ATTRIBUTE_UNUSED)
|
void *arg ATTRIBUTE_UNUSED,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unw_word label = (code & 0x1f);
|
unw_word label = (code & 0x1f);
|
||||||
|
|
||||||
@ -997,7 +983,8 @@ unw_decode_b1 (const unsigned char *dp, unsigned int code,
|
|||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_b2 (const unsigned char *dp, unsigned int code,
|
unw_decode_b2 (const unsigned char *dp, unsigned int code,
|
||||||
void *arg ATTRIBUTE_UNUSED)
|
void *arg ATTRIBUTE_UNUSED,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unw_word t;
|
unw_word t;
|
||||||
|
|
||||||
@ -1007,7 +994,8 @@ unw_decode_b2 (const unsigned char *dp, unsigned int code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char *
|
static const unsigned char *
|
||||||
unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
|
unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg,
|
||||||
|
const unsigned char * end ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unw_word t, ecount, label;
|
unw_word t, ecount, label;
|
||||||
|
|
||||||
@ -1044,7 +1032,7 @@ unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef const unsigned char *(*unw_decoder)
|
typedef const unsigned char *(*unw_decoder)
|
||||||
(const unsigned char *, unsigned int, void *);
|
(const unsigned char *, unsigned int, void *, const unsigned char *);
|
||||||
|
|
||||||
static const unw_decoder unw_decode_table[2][8] =
|
static const unw_decoder unw_decode_table[2][8] =
|
||||||
{
|
{
|
||||||
@ -1074,12 +1062,12 @@ static const unw_decoder unw_decode_table[2][8] =
|
|||||||
/* Decode one descriptor and return address of next descriptor. */
|
/* Decode one descriptor and return address of next descriptor. */
|
||||||
const unsigned char *
|
const unsigned char *
|
||||||
unw_decode (const unsigned char *dp, int inside_body,
|
unw_decode (const unsigned char *dp, int inside_body,
|
||||||
void *ptr_inside_body)
|
void *ptr_inside_body, const unsigned char * end)
|
||||||
{
|
{
|
||||||
unw_decoder decoder;
|
unw_decoder decoder;
|
||||||
unsigned char code;
|
unsigned char code;
|
||||||
|
|
||||||
code = *dp++;
|
code = *dp++;
|
||||||
decoder = unw_decode_table[inside_body][code >> 5];
|
decoder = unw_decode_table[inside_body][code >> 5];
|
||||||
return (*decoder) (dp, code, ptr_inside_body);
|
return (*decoder) (dp, code, ptr_inside_body, end);
|
||||||
}
|
}
|
||||||
|
@ -29,4 +29,4 @@
|
|||||||
#define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000LL)
|
#define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000LL)
|
||||||
#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffLL)
|
#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffLL)
|
||||||
|
|
||||||
extern const unsigned char *unw_decode (const unsigned char *, int, void *);
|
extern const unsigned char *unw_decode (const unsigned char *, int, void *, const unsigned char *);
|
||||||
|
Loading…
Reference in New Issue
Block a user