summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-01-14 10:45:41 +1030
committerAlan Modra <amodra@gmail.com>2020-01-14 11:02:37 +1030
commitef4e5ba50c76511d4306edf1526c15269f1d7747 (patch)
tree271d3f426614b1941f954ab6181e8db0a9f0649a
parent8ab484c23b9f3533fcd942e95887383786331f06 (diff)
downloadbinutils-gdb-ef4e5ba50c76511d4306edf1526c15269f1d7747.tar.gz
som: Don't loop forever reading symbol chains
* som.c (som_bfd_count_ar_symbols): Error when file position of symbols on chains is not strictly increasing.
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/som.c13
2 files changed, 16 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index acb545cd03c..75099e91b22 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,10 @@
2020-01-14 Alan Modra <amodra@gmail.com>
+ * som.c (som_bfd_count_ar_symbols): Error when file position
+ of symbols on chains is not strictly increasing.
+
+2020-01-14 Alan Modra <amodra@gmail.com>
+
* vms.h (VMS_DEBUG): Define as 0.
* vms-alpha.c (image_write): Move debug output after bounds check.
Tidy bounds check.
diff --git a/bfd/som.c b/bfd/som.c
index 779fd5d3883..8e8960ed83f 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;