readelf: NULL dereference

Alan Modra amodra@gmail.com
Sun Apr 26 14:19:42 GMT 2020


This fixes another missing error check.

	* readelf.c (get_num_dynamic_syms): Check DT_MIPS_XHASH was
	read before dereferencing, and gracefully return.  Remove
	gnu_hash_error variable.  Free gnu hash arrays if number of
	syms found is zero.

diff --git a/binutils/readelf.c b/binutils/readelf.c
index 8e8ade8fbe..68dfa32f1f 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -10026,7 +10026,6 @@ get_num_dynamic_syms (Filedata * filedata)
       bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
       bfd_vma buckets_vma;
       unsigned long hn;
-      bfd_boolean gnu_hash_error = FALSE;
 
       if (fseek (filedata->handle,
 		 (filedata->archive_file_offset
@@ -10036,14 +10035,12 @@ get_num_dynamic_syms (Filedata * filedata)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  gnu_hash_error = TRUE;
 	  goto no_gnu_hash;
 	}
 
       if (fread (nb, 16, 1, filedata->handle) != 1)
 	{
 	  error (_("Failed to read in number of buckets\n"));
-	  gnu_hash_error = TRUE;
 	  goto no_gnu_hash;
 	}
 
@@ -10062,7 +10059,6 @@ get_num_dynamic_syms (Filedata * filedata)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  gnu_hash_error = TRUE;
 	  goto no_gnu_hash;
 	}
 
@@ -10070,29 +10066,20 @@ get_num_dynamic_syms (Filedata * filedata)
 	= get_dynamic_data (filedata, filedata->ngnubuckets, 4);
 
       if (filedata->gnubuckets == NULL)
-	{
-	  gnu_hash_error = TRUE;
-	  goto no_gnu_hash;
-	}
+	goto no_gnu_hash;
 
       for (i = 0; i < filedata->ngnubuckets; i++)
 	if (filedata->gnubuckets[i] != 0)
 	  {
 	    if (filedata->gnubuckets[i] < filedata->gnusymidx)
-	      {
-		gnu_hash_error = TRUE;
-		goto no_gnu_hash;
-	      }
+	      goto no_gnu_hash;
 
 	    if (maxchain == 0xffffffff || filedata->gnubuckets[i] > maxchain)
 	      maxchain = filedata->gnubuckets[i];
 	  }
 
       if (maxchain == 0xffffffff)
-	{
-	  gnu_hash_error = TRUE;
-	  goto no_gnu_hash;
-	}
+	goto no_gnu_hash;
 
       maxchain -= filedata->gnusymidx;
 
@@ -10105,7 +10092,6 @@ get_num_dynamic_syms (Filedata * filedata)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  gnu_hash_error = TRUE;
 	  goto no_gnu_hash;
 	}
 
@@ -10114,15 +10100,11 @@ get_num_dynamic_syms (Filedata * filedata)
 	  if (fread (nb, 4, 1, filedata->handle) != 1)
 	    {
 	      error (_("Failed to determine last chain length\n"));
-	      gnu_hash_error = TRUE;
 	      goto no_gnu_hash;
 	    }
 
 	  if (maxchain + 1 == 0)
-	    {
-	      gnu_hash_error = TRUE;
-	      goto no_gnu_hash;
-	    }
+	    goto no_gnu_hash;
 
 	  ++maxchain;
 	}
@@ -10136,7 +10118,6 @@ get_num_dynamic_syms (Filedata * filedata)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  gnu_hash_error = TRUE;
 	  goto no_gnu_hash;
 	}
 
@@ -10144,10 +10125,7 @@ get_num_dynamic_syms (Filedata * filedata)
       filedata->ngnuchains = maxchain;
 
       if (filedata->gnuchains == NULL)
-	{
-	  gnu_hash_error = TRUE;
-	  goto no_gnu_hash;
-	}
+	goto no_gnu_hash;
 
       if (filedata->dynamic_info_DT_MIPS_XHASH)
 	{
@@ -10159,11 +10137,12 @@ get_num_dynamic_syms (Filedata * filedata)
 		     SEEK_SET))
 	    {
 	      error (_("Unable to seek to start of dynamic information\n"));
-	      gnu_hash_error = TRUE;
 	      goto no_gnu_hash;
 	    }
 
 	  filedata->mipsxlat = get_dynamic_data (filedata, maxchain, 4);
+	  if (filedata->mipsxlat == NULL)
+	    goto no_gnu_hash;
 	}
 
       for (hn = 0; hn < filedata->ngnubuckets; ++hn)
@@ -10190,9 +10169,9 @@ get_num_dynamic_syms (Filedata * filedata)
 		   && (filedata->gnuchains[off++] & 1) == 0);
 	  }
 
-    no_gnu_hash:
-      if (gnu_hash_error)
+      if (num_of_syms == 0)
 	{
+	no_gnu_hash:
 	  if (filedata->mipsxlat)
 	    {
 	      free (filedata->mipsxlat);

-- 
Alan Modra
Australia Development Lab, IBM


More information about the Binutils mailing list