[binutils-gdb] Integer overflows in readelf get_data

Alan Modra amodra@sourceware.org
Wed Aug 7 14:46:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7c1c1904bedb8f873731651b420a23f573785728

commit 7c1c1904bedb8f873731651b420a23f573785728
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Aug 7 23:37:49 2019 +0930

    Integer overflows in readelf get_data
    
    I noticed the test for overflow of amt = size * nmemb in get_data
    wasn't effective.  An obvious example of nmemb = 3 and size = half max
    value overflows but doesn't result in amt < nmemb.  This patch fixes
    this problem and reports a size truncation or overflow rather than out
    of memory in more cases.
    
    	* readelf.c (get_data): Improve overflow checks.

Diff:
---
 binutils/ChangeLog |  4 ++++
 binutils/readelf.c | 14 ++++++--------
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index c5d2d8f..b60ae64 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,7 @@
+2019-08-08  Alan Modra  <amodra@gmail.com>
+
+	* readelf.c (get_data): Improve overflow checks.
+
 2019-08-07  Nick Clifton  <nickc@redhat.com>
 
 	PR 24777
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 5e18734..3e3e27d 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -385,9 +385,9 @@ get_data (void *         var,
   /* If the size_t type is smaller than the bfd_size_type, eg because
      you are building a 32-bit tool on a 64-bit host, then make sure
      that when the sizes are cast to (size_t) no information is lost.  */
-  if (sizeof (size_t) < sizeof (bfd_size_type)
-      && (   (bfd_size_type) ((size_t) size) != size
-	  || (bfd_size_type) ((size_t) nmemb) != nmemb))
+  if ((size_t) size != size
+      || (size_t) nmemb != nmemb
+      || (size_t) amt != amt)
     {
       if (reason)
 	error (_("Size truncation prevents reading %s"
@@ -397,7 +397,7 @@ get_data (void *         var,
     }
 
   /* Check for size overflow.  */
-  if (amt < nmemb)
+  if (amt / size != nmemb || (size_t) amt + 1 == 0)
     {
       if (reason)
 	error (_("Size overflow prevents reading %s"
@@ -429,10 +429,8 @@ get_data (void *         var,
   mvar = var;
   if (mvar == NULL)
     {
-      /* Check for overflow.  */
-      if (nmemb < (~(bfd_size_type) 0 - 1) / size)
-	/* + 1 so that we can '\0' terminate invalid string table sections.  */
-	mvar = malloc ((size_t) amt + 1);
+      /* + 1 so that we can '\0' terminate invalid string table sections.  */
+      mvar = malloc ((size_t) amt + 1);
 
       if (mvar == NULL)
 	{



More information about the Binutils-cvs mailing list