Fix more potential seg-faults in gprof.
authorNick Clifton <nickc@redhat.com>
Tue, 30 Aug 2016 12:38:54 +0000 (13:38 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 30 Aug 2016 12:38:54 +0000 (13:38 +0100)
PR gprof/20499
* corefile.c (num_of_syms_in): Return an unsigned int.
(core_create_syms_from): Catch a possible integer overflow
computing the argument to xmalloc.  Also allow for the possibility
that an integer overflow in num_of_syms_in means that less space
has been allocated than expected.

gprof/ChangeLog
gprof/corefile.c

index 1081e8fb19dde03c9d2c2798f106e84d504a8478..e5afbf635617b4d42277cbd267b6813a8e522f11 100644 (file)
@@ -1,3 +1,12 @@
+2016-08-30  Nick Clifton  <nickc@redhat.com>
+
+       PR gprof/20499
+       * corefile.c (num_of_syms_in): Return an unsigned int.
+       (core_create_syms_from): Catch a possible integer overflow
+       computing the argument to xmalloc.  Also allow for the possibility
+       that an integer overflow in num_of_syms_in means that less space
+       has been allocated than expected.
+
 2016-08-23  Nick Clifton  <nickc@redhat.com>
 
        PR gprof/20499
index 2a433a6a3ea7c12959fa32d8c7dce83a5e7a6ded..e165da2c112286afb956d79c0751f90fb3708365 100644 (file)
@@ -490,11 +490,11 @@ static char name[BUFSIZE];
 
 /* Return number of symbols in a symbol-table file.  */
 
-static int
+static unsigned int
 num_of_syms_in (FILE * f)
 {
   char   type;
-  int num = 0;
+  unsigned int num = 0;
 
   while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
     {
@@ -531,6 +531,13 @@ core_create_syms_from (const char * sym_table_file)
       fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, sym_table_file);
       done (1);
     }
+  /* PR 20499 - prevent integer overflow computing argument to xmalloc.  */
+  else if ((symtab.len * (unsigned) sizeof (Sym)) < symtab.len)
+    {
+      fprintf (stderr, _("%s: file `%s' has too many symbols: %u\n"),
+              whoami, sym_table_file, symtab.len);
+      done (1);
+    }
 
   symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
 
@@ -564,6 +571,12 @@ core_create_syms_from (const char * sym_table_file)
       max_vma = MAX (symtab.limit->addr, max_vma);
 
       ++symtab.limit;
+      /* PR 20499 - it is theoretically possible that there are so many
+        symbols in the file that the scan in num_of_syms_in() wrapped
+        around.  So be paranoid here and exit the loop if we have
+        reached the end of our allocated table.  */
+      if ((unsigned int)(symtab.limit - symtab.base) == symtab.len)
+       break;
     }
   fclose (f);