]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR30657, gprof heap buffer overflow
authorAlan Modra <amodra@gmail.com>
Wed, 26 Jul 2023 00:24:03 +0000 (09:54 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 26 Jul 2023 00:53:27 +0000 (10:23 +0930)
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.

gprof/aarch64.c
gprof/alpha.c
gprof/cg_arcs.c
gprof/i386.c
gprof/mips.c
gprof/sparc.c
gprof/vax.c

index 68febf9372341f77b4f57301b4fd90f248ad21a5..3ab6067dbac9e4e73ad52955731716628d00d9b1 100644 (file)
@@ -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)
     {
 
index d84cdf0a916e01549ea560bc287f664714672c71..df714be6c814ef32d539c1c55b8fa24e653e4929 100644 (file)
@@ -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));
index e76c2cb78cfc99d0d19cf42c4d531f52198e26f9..cfffb09ff87b68cae7ec5310e71a49c74ec6cc2e 100644 (file)
@@ -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);
     }
 
index bdf8bd1b83206db11f203303224d456a1d86f053..62f6f96b20a6ea57d04224e1022a6613bd876e74 100644 (file)
@@ -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;
index e198a6f411a54648ba035d05ac5e1d7d862367f9..0ccd17db525c2da2c83b23c70cb303b15ae36f65 100644 (file)
@@ -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
index 44724c47d3f3b61bfa47308edd991a43b391d261..019e58b185fa6434b3ea35a8de9db1d2b0c8d036 100644 (file)
@@ -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));
index 92942353b48cfd1aa17dd8889f94922c0a78941f..fafe2b17b53e6c2def76149b428ae1eb1b74b850 100644 (file)
@@ -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;
                        }
                    }