readelf: NULL dereference
authorAlan Modra <amodra@gmail.com>
Sun, 26 Apr 2020 09:00:50 +0000 (18:30 +0930)
committerAlan Modra <amodra@gmail.com>
Sun, 26 Apr 2020 14:20:18 +0000 (23:50 +0930)
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.

binutils/ChangeLog
binutils/readelf.c

index ad3846a1c2877a50c51f40668d14fbbdf7f0c86b..7fb2dbe3f9ebba938ef30575d87710d9248afad9 100644 (file)
@@ -1,3 +1,10 @@
+2020-04-26  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2020-04-24  Alan Modra  <amodra@gmail.com>
 
        * readelf.c (get_num_dynamic_syms): Check for nbuckets and nchains
index 8e8ade8fbe0b74ebf3835573fbc57ab795c7859d..68dfa32f1fa08716195c1ab76676676a330be152 100644 (file)
@@ -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);