som: Don't loop forever reading symbol chains

Message ID 20200114003630.GU4433@bubble.grove.modra.org
State New
Headers show
Series
  • som: Don't loop forever reading symbol chains
Related show

Commit Message

Alan Modra Jan. 14, 2020, 12:36 a.m.
Hopefully this doesn't break archives produced by other tools..

	* som.c (som_bfd_count_ar_symbols): Error when file position
	of symbols on chains is not strictly increasing.


-- 
Alan Modra
Australia Development Lab, IBM

Comments

John David Anglin Jan. 14, 2020, 2:18 a.m. | #1
On 2020-01-13 7:36 p.m., Alan Modra wrote:
> Hopefully this doesn't break archives produced by other tools..

>

> 	* som.c (som_bfd_count_ar_symbols): Error when file position

> 	of symbols on chains is not strictly increasing.

Test results are same as before.  There are two fails:

Version /mnt/gnu/binutils/objdir/binutils/objcopy 2.33.50.20200114
FAIL: objcopy --reverse-bytes

and

Running /mnt/gnu/binutils/src/gas/testsuite/gas/all/gas.exp ...
FAIL: .xstabs

Dave

-- 
John David Anglin  dave.anglin@bell.net

Patch

diff --git a/bfd/som.c b/bfd/som.c
index 779fd5d388..8e8960ed83 100644
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -5892,8 +5892,8 @@  som_bfd_count_ar_symbols (bfd *abfd,
   /* Don't forget to initialize the counter!  */
   *count = 0;
 
-  /* Read in the hash table.  The has table is an array of 32bit file offsets
-     which point to the hash chains.  */
+  /* Read in the hash table.  The hash table is an array of 32-bit
+     file offsets which point to the hash chains.  */
   amt = (bfd_size_type) lst_header->hash_size * 4;
   if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
     goto error_return;
@@ -5928,6 +5928,15 @@  som_bfd_count_ar_symbols (bfd *abfd,
 	  if (next_entry == 0)
 	    break;
 
+	  /* Assume symbols on a chain are in increasing file offset
+	     order.  Otherwise we can loop here with fuzzed input.  */
+	  if (next_entry < hash_val + sizeof (ext_lst_symbol))
+	    {
+	      bfd_set_error (bfd_error_bad_value);
+	      goto error_return;
+	    }
+	  hash_val = next_entry;
+
 	  /* Seek to the next symbol.  */
 	  if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
 	    goto error_return;