public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PR30657, gprof heap buffer overflow
@ 2023-07-26  0:55 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2023-07-26  0:55 UTC (permalink / raw)
  To: binutils

	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.

diff --git a/gprof/aarch64.c b/gprof/aarch64.c
index 68febf93723..3ab6067dbac 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 d84cdf0a916..df714be6c81 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 e76c2cb78cf..cfffb09ff87 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 bdf8bd1b832..62f6f96b20a 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 e198a6f411a..0ccd17db525 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 44724c47d3f..019e58b185f 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 92942353b48..fafe2b17b53 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;
 		        }
 		    }

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-07-26  0:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-26  0:55 PR30657, gprof heap buffer overflow Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).