]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR22307, Heap out of bounds read in _bfd_elf_parse_gnu_properties
authorAlan Modra <amodra@gmail.com>
Tue, 17 Oct 2017 11:27:29 +0000 (21:57 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 17 Oct 2017 11:42:45 +0000 (22:12 +1030)
When adding an unbounded increment to a pointer, you can't just check
against the end of the buffer but also must check that overflow
doesn't result in "negative" pointer movement.  Pointer comparisons
are signed.  Better, check the increment against the space left using
an unsigned comparison.

PR 22307
* elf-properties.c (_bfd_elf_parse_gnu_properties): Compare datasz
against size left rather than comparing pointers.  Reorganise loop.

bfd/ChangeLog
bfd/elf-properties.c

index 6f2c2b71de614249675206c3d537002b44d56d23..237381680647c2d927279f16eb277b93e03aec0a 100644 (file)
@@ -1,3 +1,9 @@
+2017-10-17  Alan Modra  <amodra@gmail.com>
+
+       PR 22307
+       * elf-properties.c (_bfd_elf_parse_gnu_properties): Compare datasz
+       against size left rather than comparing pointers.  Reorganise loop.
+
 2017-10-17  Alan Modra  <amodra@gmail.com>
 
        PR 22306
index f367aa69417ce62df2ba897cd40a5d7128568a82..bfb106edc92d1f80035f40ac32e419a9f495ee98 100644 (file)
@@ -93,15 +93,20 @@ bad_size:
       return FALSE;
     }
 
-  while (1)
+  while (ptr != ptr_end)
     {
-      unsigned int type = bfd_h_get_32 (abfd, ptr);
-      unsigned int datasz = bfd_h_get_32 (abfd, ptr + 4);
+      unsigned int type;
+      unsigned int datasz;
       elf_property *prop;
 
+      if ((size_t) (ptr_end - ptr) < 8)
+       goto bad_size;
+
+      type = bfd_h_get_32 (abfd, ptr);
+      datasz = bfd_h_get_32 (abfd, ptr + 4);
       ptr += 8;
 
-      if ((ptr + datasz) > ptr_end)
+      if (datasz > (size_t) (ptr_end - ptr))
        {
          _bfd_error_handler
            (_("warning: %B: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"),
@@ -183,11 +188,6 @@ bad_size:
 
 next:
       ptr += (datasz + (align_size - 1)) & ~ (align_size - 1);
-      if (ptr == ptr_end)
-       break;
-
-      if (ptr > (ptr_end - 8))
-       goto bad_size;
     }
 
   return TRUE;