PR binutils/15191
authorAlan Modra <amodra@gmail.com>
Wed, 27 Feb 2013 12:40:15 +0000 (12:40 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 27 Feb 2013 12:40:15 +0000 (12:40 +0000)
* readelf.c (offsetof): Define.
(CHECK_ENTSIZE_VALUES): Remove extraneous indefinite article.
(process_corefile_note_segment): Allow notes without name or
desc.  Combine out-of-range checks.  Disallow "negative"
notesz or descsz.

binutils/ChangeLog
binutils/readelf.c

index 8d06ecb..01ac46d 100644 (file)
@@ -1,3 +1,12 @@
+2013-02-27  Alan Modra  <amodra@gmail.com>
+
+       PR binutils/15191
+       * readelf.c (offsetof): Define.
+       (CHECK_ENTSIZE_VALUES): Remove extraneous indefinite article.
+       (process_corefile_note_segment): Allow notes without name or
+       desc.  Combine out-of-range checks.  Disallow "negative"
+       notesz or descsz.
+
 2013-02-26  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/15191
 
 2013-01-25  Cary Coutant  <ccoutant@google.com>
 
-       * dwarf.c (display_loc_list): Update offset for each line
-       printed.
-       (print_addr_index): New function.
-       (display_loc_list_dwo): Update offset for each line printed.
-       Fix problems displaying loclists in .dwo files.  Add support
-       for type 4 entries.
-       (display_debug_loc): Remove custom header for .dwo files.
-       (display_debug_addr): Adjust formatting.
+       * dwarf.c (display_loc_list): Update offset for each line
+       printed.
+       (print_addr_index): New function.
+       (display_loc_list_dwo): Update offset for each line printed.
+       Fix problems displaying loclists in .dwo files.  Add support
+       for type 4 entries.
+       (display_debug_loc): Remove custom header for .dwo files.
+       (display_debug_addr): Adjust formatting.
 
 2013-01-25  Marco Atzeri  <marco.atzeri@gmail.com>
 
index 7b9d102..28172f2 100644 (file)
 #include "safe-ctype.h"
 #include "filenames.h"
 
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *) 0)->MEMBER))
+#endif
+
 char * program_name = "readelf";
 static long archive_file_offset;
 static unsigned long archive_file_size;
@@ -4754,7 +4758,7 @@ process_section_headers (FILE * file)
       bfd_size_type expected_entsize = is_32bit_elf ? size32 : size64;     \
       if (section->sh_entsize != expected_entsize)                         \
        {                                                               \
-         error (_("Section %d has invalid an sh_entsize of %" BFD_VMA_FMT "x\n"), \
+         error (_("Section %d has invalid sh_entsize of %" BFD_VMA_FMT "x\n"), \
                 i, section->sh_entsize);       \
          error (_("(Using the expected size of %d for the rest of this dump)\n"), \
                   (int) expected_entsize); \
@@ -13340,13 +13344,12 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
   Elf_External_Note * pnotes;
   Elf_External_Note * external;
   int res = 1;
-  bfd_signed_vma data_remaining;
 
   if (length <= 0)
     return 0;
 
   pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
-                                           _("notes"));
+                                          _("notes"));
   if (pnotes == NULL)
     return 0;
 
@@ -13356,79 +13359,69 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
          (unsigned long) offset, (unsigned long) length);
   printf (_("  %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
 
-  data_remaining = length;
-  while (external < (Elf_External_Note *) ((char *) pnotes + length))
+  while ((char *) external < (char *) pnotes + length)
     {
-      Elf_External_Note * next;
       Elf_Internal_Note inote;
+      size_t min_notesz;
+      char *next;
       char * temp = NULL;
+      size_t data_remaining = ((char *) pnotes + length) - (char *) external;
 
       if (!is_ia64_vms ())
-        {
+       {
          /* PR binutils/15191
             Make sure that there is enough data to read.  */
-         if (data_remaining < sizeof * next)
+         min_notesz = offsetof (Elf_External_Note, name);
+         if (data_remaining < min_notesz)
            {
              warn (_("Corrupt note: only %d bytes remain, not enough for a full note\n"),
                    (int) data_remaining);
              break;
            }
-          inote.type     = BYTE_GET (external->type);
-          inote.namesz   = BYTE_GET (external->namesz);
-          inote.namedata = external->name;
-          inote.descsz   = BYTE_GET (external->descsz);
-          inote.descdata = inote.namedata + align_power (inote.namesz, 2);
-          inote.descpos  = offset + (inote.descdata - (char *) pnotes);
-
-          next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
-        }
+         inote.type     = BYTE_GET (external->type);
+         inote.namesz   = BYTE_GET (external->namesz);
+         inote.namedata = external->name;
+         inote.descsz   = BYTE_GET (external->descsz);
+         inote.descdata = inote.namedata + align_power (inote.namesz, 2);
+         inote.descpos  = offset + (inote.descdata - (char *) pnotes);
+         next = inote.descdata + align_power (inote.descsz, 2);
+       }
       else
-        {
-          Elf64_External_VMS_Note *vms_external;
+       {
+         Elf64_External_VMS_Note *vms_external;
 
          /* PR binutils/15191
             Make sure that there is enough data to read.  */
-         if (data_remaining < sizeof * vms_external)
+         min_notesz = offsetof (Elf64_External_VMS_Note, name);
+         if (data_remaining < min_notesz)
            {
              warn (_("Corrupt note: only %d bytes remain, not enough for a full note\n"),
                    (int) data_remaining);
              break;
            }
-         
-          vms_external = (Elf64_External_VMS_Note *) external;
-          inote.type     = BYTE_GET (vms_external->type);
-          inote.namesz   = BYTE_GET (vms_external->namesz);
-          inote.namedata = vms_external->name;
-          inote.descsz   = BYTE_GET (vms_external->descsz);
-          inote.descdata = inote.namedata + align_power (inote.namesz, 3);
-          inote.descpos  = offset + (inote.descdata - (char *) pnotes);
-
-          next = (Elf_External_Note *)
-            (inote.descdata + align_power (inote.descsz, 3));
-        }
 
-      data_remaining -= ((char *) next - (char *) external);
-      if (data_remaining < 0)
+         vms_external = (Elf64_External_VMS_Note *) external;
+         inote.type     = BYTE_GET (vms_external->type);
+         inote.namesz   = BYTE_GET (vms_external->namesz);
+         inote.namedata = vms_external->name;
+         inote.descsz   = BYTE_GET (vms_external->descsz);
+         inote.descdata = inote.namedata + align_power (inote.namesz, 3);
+         inote.descpos  = offset + (inote.descdata - (char *) pnotes);
+         next = inote.descdata + align_power (inote.descsz, 3);
+       }
+
+      if (inote.descdata < (char *) external + min_notesz
+         || next < (char *) external + min_notesz
+         || data_remaining < (size_t)(next - (char *) external))
        {
-         warn (_("note with invalid namesz &/or descsz found at offset 0x%lx\n"),
+         warn (_("note with invalid namesz and/or descsz found at offset 0x%lx\n"),
                (unsigned long) ((char *) external - (char *) pnotes));
          warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
                inote.type, inote.namesz, inote.descsz);
          break;
        }
 
-      external = next;
-
-      /* Prevent out-of-bounds indexing.  */
-      if (inote.namedata + inote.namesz > (char *) pnotes + length
-         || inote.namedata + inote.namesz < inote.namedata)
-        {
-          warn (_("note with invalid namesz found at offset 0x%lx\n"),
-                (unsigned long) ((char *) external - (char *) pnotes));
-          warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
-                inote.type, inote.namesz, inote.descsz);
-          break;
-        }
+      external = (Elf_External_Note *) next;
 
       /* Verify that name is null terminated.  It appears that at least
         one version of Linux (RedHat 6.0) generates corefiles that don't