forked from Imagelibrary/binutils-gdb
PR30657, gprof heap buffer overflow
PR 30657 * cg_arcs.c (cg_assemble): Sanity check find_call addresses. * i386.c (i386_find_call): Don't access past end of core_text_space. * aarch64.c (aarch64_find_call): Round up lowpc, round down highpc. * alpha.c (alpha_find_call): Likewise. * mips.c (mips_find_call): Likewise. * sparc.c (sparc_find_call): Likewise. * vax.c (vax_find_call): Sanity check core_text_space accesses.
This commit is contained in:
@@ -54,7 +54,8 @@ aarch64_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
|
DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
|
||||||
parent->name, (unsigned long) p_lowpc,
|
parent->name, (unsigned long) p_lowpc,
|
||||||
(unsigned long) p_highpc));
|
(unsigned long) p_highpc));
|
||||||
|
p_lowpc = (p_lowpc + 3) & ~3;
|
||||||
|
p_highpc &= ~3;
|
||||||
for (pc = p_lowpc; pc < p_highpc; pc += 4)
|
for (pc = p_lowpc; pc < p_highpc; pc += 4)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,9 @@ alpha_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
|
DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
|
||||||
parent->name, (unsigned long) p_lowpc,
|
parent->name, (unsigned long) p_lowpc,
|
||||||
(unsigned long) p_highpc));
|
(unsigned long) p_highpc));
|
||||||
for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
|
p_lowpc = (p_lowpc + 3) & ~3;
|
||||||
|
p_highpc &= ~3;
|
||||||
|
for (pc = p_lowpc; pc < p_highpc; pc += 4)
|
||||||
{
|
{
|
||||||
insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
|
insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
|
||||||
+ pc - core_text_sect->vma));
|
+ pc - core_text_sect->vma));
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "cg_print.h"
|
#include "cg_print.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sym_ids.h"
|
#include "sym_ids.h"
|
||||||
|
#include "corefile.h"
|
||||||
|
|
||||||
static int cmp_topo (const void *, const void *);
|
static int cmp_topo (const void *, const void *);
|
||||||
static void propagate_time (Sym *);
|
static void propagate_time (Sym *);
|
||||||
@@ -622,7 +623,11 @@ cg_assemble (void)
|
|||||||
parent->cg.cyc.num = 0;
|
parent->cg.cyc.num = 0;
|
||||||
parent->cg.cyc.head = parent;
|
parent->cg.cyc.head = parent;
|
||||||
parent->cg.cyc.next = 0;
|
parent->cg.cyc.next = 0;
|
||||||
if (ignore_direct_calls)
|
if (ignore_direct_calls
|
||||||
|
&& parent->addr >= core_text_sect->vma
|
||||||
|
&& parent->addr < core_text_sect->vma + core_text_sect->size
|
||||||
|
&& (parent + 1)->addr >= core_text_sect->vma
|
||||||
|
&& (parent + 1)->addr <= core_text_sect->vma + core_text_sect->size)
|
||||||
find_call (parent, parent->addr, (parent + 1)->addr);
|
find_call (parent, parent->addr, (parent + 1)->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ i386_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
parent->name, (unsigned long) p_lowpc,
|
parent->name, (unsigned long) p_lowpc,
|
||||||
(unsigned long) p_highpc));
|
(unsigned long) p_highpc));
|
||||||
|
|
||||||
|
if (p_highpc < 5)
|
||||||
|
return;
|
||||||
|
p_highpc -= 5;
|
||||||
for (pc = p_lowpc; pc < p_highpc; ++pc)
|
for (pc = p_lowpc; pc < p_highpc; ++pc)
|
||||||
{
|
{
|
||||||
instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma;
|
instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma;
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ mips_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
|
DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
|
||||||
parent->name, (unsigned long) p_lowpc,
|
parent->name, (unsigned long) p_lowpc,
|
||||||
(unsigned long) p_highpc));
|
(unsigned long) p_highpc));
|
||||||
|
p_lowpc = (p_lowpc + 3) & ~3;
|
||||||
|
p_highpc &= ~3;
|
||||||
for (pc = p_lowpc; pc < p_highpc; pc += 4)
|
for (pc = p_lowpc; pc < p_highpc; pc += 4)
|
||||||
{
|
{
|
||||||
op = bfd_get_32 (core_bfd, ((unsigned char *)core_text_space
|
op = bfd_get_32 (core_bfd, ((unsigned char *)core_text_space
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ sparc_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
|
DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
|
||||||
parent->name, (unsigned long) p_lowpc,
|
parent->name, (unsigned long) p_lowpc,
|
||||||
(unsigned long) p_highpc));
|
(unsigned long) p_highpc));
|
||||||
for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
|
p_lowpc = (p_lowpc + 3) & ~3;
|
||||||
|
p_highpc &= ~3;
|
||||||
|
for (pc = p_lowpc; pc < p_highpc; pc += 4)
|
||||||
{
|
{
|
||||||
insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
|
insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
|
||||||
+ pc - core_text_sect->vma));
|
+ pc - core_text_sect->vma));
|
||||||
|
|||||||
24
gprof/vax.c
24
gprof/vax.c
@@ -252,6 +252,8 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
(unsigned long) p_highpc));
|
(unsigned long) p_highpc));
|
||||||
for (pc = p_lowpc; pc < p_highpc; pc += length)
|
for (pc = p_lowpc; pc < p_highpc; pc += length)
|
||||||
{
|
{
|
||||||
|
unsigned char *operand;
|
||||||
|
|
||||||
length = 1;
|
length = 1;
|
||||||
instructp = ((unsigned char *) core_text_space
|
instructp = ((unsigned char *) core_text_space
|
||||||
+ pc - core_text_sect->vma);
|
+ pc - core_text_sect->vma);
|
||||||
@@ -263,7 +265,10 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
*/
|
*/
|
||||||
DBG (CALLDEBUG,
|
DBG (CALLDEBUG,
|
||||||
printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
|
printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
|
||||||
firstmode = vax_operandmode (instructp + length);
|
if (pc - core_text_sect->vma + length >= core_text_sect->size)
|
||||||
|
goto botched;
|
||||||
|
operand = instructp + length;
|
||||||
|
firstmode = vax_operandmode (operand);
|
||||||
switch (firstmode)
|
switch (firstmode)
|
||||||
{
|
{
|
||||||
case literal:
|
case literal:
|
||||||
@@ -272,8 +277,11 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
default:
|
default:
|
||||||
goto botched;
|
goto botched;
|
||||||
}
|
}
|
||||||
length += vax_operandlength (instructp + length);
|
length += vax_operandlength (operand);
|
||||||
mode = vax_operandmode (instructp + length);
|
if (pc - core_text_sect->vma + length >= core_text_sect->size)
|
||||||
|
goto botched;
|
||||||
|
operand = instructp + length;
|
||||||
|
mode = vax_operandmode (operand);
|
||||||
DBG (CALLDEBUG,
|
DBG (CALLDEBUG,
|
||||||
printf ("\tfirst operand is %s", vax_operandname (firstmode));
|
printf ("\tfirst operand is %s", vax_operandname (firstmode));
|
||||||
printf ("\tsecond operand is %s\n", vax_operandname (mode)));
|
printf ("\tsecond operand is %s\n", vax_operandname (mode)));
|
||||||
@@ -294,8 +302,10 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
* [are there others that we miss?,
|
* [are there others that we miss?,
|
||||||
* e.g. arrays of pointers to functions???]
|
* e.g. arrays of pointers to functions???]
|
||||||
*/
|
*/
|
||||||
|
length += vax_operandlength (operand);
|
||||||
|
if (pc - core_text_sect->vma + length > core_text_sect->size)
|
||||||
|
goto botched;
|
||||||
arc_add (parent, &indirectchild, (unsigned long) 0);
|
arc_add (parent, &indirectchild, (unsigned long) 0);
|
||||||
length += vax_operandlength (instructp + length);
|
|
||||||
continue;
|
continue;
|
||||||
case byterel:
|
case byterel:
|
||||||
case wordrel:
|
case wordrel:
|
||||||
@@ -305,7 +315,10 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
* check that this is the address of
|
* check that this is the address of
|
||||||
* a function.
|
* a function.
|
||||||
*/
|
*/
|
||||||
destpc = pc + vax_offset (instructp + length);
|
length += vax_operandlength (operand);
|
||||||
|
if (pc - core_text_sect->vma + length > core_text_sect->size)
|
||||||
|
goto botched;
|
||||||
|
destpc = pc + vax_offset (operand);
|
||||||
if (hist_check_address (destpc))
|
if (hist_check_address (destpc))
|
||||||
{
|
{
|
||||||
child = sym_lookup (&symtab, destpc);
|
child = sym_lookup (&symtab, destpc);
|
||||||
@@ -324,7 +337,6 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
|
|||||||
* a hit
|
* a hit
|
||||||
*/
|
*/
|
||||||
arc_add (parent, child, (unsigned long) 0);
|
arc_add (parent, child, (unsigned long) 0);
|
||||||
length += vax_operandlength (instructp + length);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user