aboutsummaryrefslogtreecommitdiff
path: root/gprof
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2023-07-26 09:54:03 +0930
committerAlan Modra <amodra@gmail.com>2023-07-26 10:23:27 +0930
commit477c9f2ba26ccd77016f2c97941fc8b35e332e35 (patch)
tree7101fd32ce2079ad0dc7006ddf9d54251af2b320 /gprof
parenteb14a8b4bfb767beebfb54d7911da4132b5c0f94 (diff)
downloadfsf-binutils-gdb-477c9f2ba26ccd77016f2c97941fc8b35e332e35.zip
fsf-binutils-gdb-477c9f2ba26ccd77016f2c97941fc8b35e332e35.tar.gz
fsf-binutils-gdb-477c9f2ba26ccd77016f2c97941fc8b35e332e35.tar.bz2
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.
Diffstat (limited to 'gprof')
-rw-r--r--gprof/aarch64.c3
-rw-r--r--gprof/alpha.c4
-rw-r--r--gprof/cg_arcs.c7
-rw-r--r--gprof/i386.c3
-rw-r--r--gprof/mips.c2
-rw-r--r--gprof/sparc.c4
-rw-r--r--gprof/vax.c24
7 files changed, 37 insertions, 10 deletions
diff --git a/gprof/aarch64.c b/gprof/aarch64.c
index 68febf9..3ab6067 100644
--- a/gprof/aarch64.c
+++ b/gprof/aarch64.c
@@ -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",
parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc));
-
+ p_lowpc = (p_lowpc + 3) & ~3;
+ p_highpc &= ~3;
for (pc = p_lowpc; pc < p_highpc; pc += 4)
{
diff --git a/gprof/alpha.c b/gprof/alpha.c
index d84cdf0..df714be 100644
--- a/gprof/alpha.c
+++ b/gprof/alpha.c
@@ -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"),
parent->name, (unsigned long) p_lowpc,
(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
+ pc - core_text_sect->vma));
diff --git a/gprof/cg_arcs.c b/gprof/cg_arcs.c
index e76c2cb..cfffb09 100644
--- a/gprof/cg_arcs.c
+++ b/gprof/cg_arcs.c
@@ -37,6 +37,7 @@
#include "cg_print.h"
#include "utils.h"
#include "sym_ids.h"
+#include "corefile.h"
static int cmp_topo (const void *, const void *);
static void propagate_time (Sym *);
@@ -622,7 +623,11 @@ cg_assemble (void)
parent->cg.cyc.num = 0;
parent->cg.cyc.head = parent;
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);
}
diff --git a/gprof/i386.c b/gprof/i386.c
index bdf8bd1..62f6f96 100644
--- a/gprof/i386.c
+++ b/gprof/i386.c
@@ -57,6 +57,9 @@ i386_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc));
+ if (p_highpc < 5)
+ return;
+ p_highpc -= 5;
for (pc = p_lowpc; pc < p_highpc; ++pc)
{
instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma;
diff --git a/gprof/mips.c b/gprof/mips.c
index e198a6f..0ccd17d 100644
--- a/gprof/mips.c
+++ b/gprof/mips.c
@@ -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"),
parent->name, (unsigned long) p_lowpc,
(unsigned long) p_highpc));
+ p_lowpc = (p_lowpc + 3) & ~3;
+ p_highpc &= ~3;
for (pc = p_lowpc; pc < p_highpc; pc += 4)
{
op = bfd_get_32 (core_bfd, ((unsigned char *)core_text_space
diff --git a/gprof/sparc.c b/gprof/sparc.c
index 44724c4..019e58b 100644
--- a/gprof/sparc.c
+++ b/gprof/sparc.c
@@ -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",
parent->name, (unsigned long) p_lowpc,
(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
+ pc - core_text_sect->vma));
diff --git a/gprof/vax.c b/gprof/vax.c
index 9294235..fafe2b1 100644
--- a/gprof/vax.c
+++ b/gprof/vax.c
@@ -252,6 +252,8 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
(unsigned long) p_highpc));
for (pc = p_lowpc; pc < p_highpc; pc += length)
{
+ unsigned char *operand;
+
length = 1;
instructp = ((unsigned char *) core_text_space
+ pc - core_text_sect->vma);
@@ -263,7 +265,10 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
*/
DBG (CALLDEBUG,
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)
{
case literal:
@@ -272,8 +277,11 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
default:
goto botched;
}
- length += vax_operandlength (instructp + length);
- mode = vax_operandmode (instructp + length);
+ length += vax_operandlength (operand);
+ if (pc - core_text_sect->vma + length >= core_text_sect->size)
+ goto botched;
+ operand = instructp + length;
+ mode = vax_operandmode (operand);
DBG (CALLDEBUG,
printf ("\tfirst operand is %s", vax_operandname (firstmode));
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?,
* 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);
- length += vax_operandlength (instructp + length);
continue;
case byterel:
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
* 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))
{
child = sym_lookup (&symtab, destpc);
@@ -324,7 +337,6 @@ vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
* a hit
*/
arc_add (parent, child, (unsigned long) 0);
- length += vax_operandlength (instructp + length);
continue;
}
}