More fixes for memory access violations exposed by fuzzed binaries.
authorNick Clifton <nickc@redhat.com>
Mon, 1 Dec 2014 16:43:46 +0000 (16:43 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 1 Dec 2014 16:43:46 +0000 (16:43 +0000)
PR binutils/17512
* dwarf.h (struct dwarf_section): Add user_data field.
* dwarf.c (frame_need_space): Check for an over large register
number.
(display_debug_frames): Check the return value from
frame_need_space.  Check for a CFA expression that is so long the
start address wraps around.
(debug_displays): Initialise the user_data field.
* objdump.c (load_specific_debug_section): Save the BFD section
pointer in the user_data field of the dwarf_section structure.
(free_debug_section): Update BFD section data when freeing section
contents.
* readelf.c (load_specific_debug_section): Initialise the
user_data field.

* archive.c (do_slurp_coff_armap): Add range checks to prevent
running off the end of the string table.
* compress.c (bfd_get_full_section_contents): Return a NULL
pointer for zero sized sections.  Do not attempt to copy a buffer
onto itself.
* elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
header.  Add range checks to avoid running off the end of the
section.
* elf.c (bfd_elf_get_str_section): Seek before allocating so that
if the seek fails, no memory is allocated.
(bfd_elf_string_from_elf_section): Do not allocate a string from a
non string section.  It only leads to trouble later on.
(_bfd_elf_print_private_bfd_data): Check for there being too
little external dynamic data.
(bfd_section_from_shdr): Replace assertion with a failure mode.
(bfd_section_from_shdr): When walking a loaded group section use
the internal structure size, not the external size.  Check for the
group section being empty.
* elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
failure mode.
* elfcode.h (elf_slurp_reloc_table): Likewise.
* reloc.c (bfd_perform_relocation): Avoid seg-fault if the howto
parameter is NULL.

13 files changed:
bfd/ChangeLog
bfd/archive.c
bfd/compress.c
bfd/elf-attrs.c
bfd/elf.c
bfd/elf32-i386.c
bfd/elfcode.h
bfd/reloc.c
binutils/ChangeLog
binutils/dwarf.c
binutils/dwarf.h
binutils/objdump.c
binutils/readelf.c

index 8bcbc11..0489b79 100644 (file)
@@ -1,3 +1,30 @@
+2014-12-01  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/17512
+       * archive.c (do_slurp_coff_armap): Add range checks to prevent
+       running off the end of the string table.
+       * compress.c (bfd_get_full_section_contents): Return a NULL
+       pointer for zero sized sections.  Do not attempt to copy a buffer
+       onto itself.
+       * elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
+       header.  Add range checks to avoid running off the end of the
+       section.
+       * elf.c (bfd_elf_get_str_section): Seek before allocating so that
+       if the seek fails, no memory is allocated.
+       (bfd_elf_string_from_elf_section): Do not allocate a string from a
+       non string section.  It only leads to trouble later on.
+       (_bfd_elf_print_private_bfd_data): Check for there being too
+       little external dynamic data.
+       (bfd_section_from_shdr): Replace assertion with a failure mode.
+       (bfd_section_from_shdr): When walking a loaded group section use
+       the internal structure size, not the external size.  Check for the
+       group section being empty.
+       * elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
+       failure mode.
+       * elfcode.h (elf_slurp_reloc_table): Likewise.
+       * reloc.c (bfd_perform_relocation): Avoid seg-fault if the howto
+       parameter is NULL.
+
 2014-11-30  Alan Modra  <amodra@gmail.com>
 
        PR 16452, 16457
 2014-11-30  Alan Modra  <amodra@gmail.com>
 
        PR 16452, 16457
index df37996..0ab4f6e 100644 (file)
@@ -1038,12 +1038,19 @@ do_slurp_coff_armap (bfd *abfd)
     }
 
   /* OK, build the carsyms.  */
     }
 
   /* OK, build the carsyms.  */
-  for (i = 0; i < nsymz; i++)
+  for (i = 0; i < nsymz && stringsize > 0; i++)
     {
     {
+      bfd_size_type len;
+
       rawptr = raw_armap + i;
       carsyms->file_offset = swap ((bfd_byte *) rawptr);
       carsyms->name = stringbase;
       rawptr = raw_armap + i;
       carsyms->file_offset = swap ((bfd_byte *) rawptr);
       carsyms->name = stringbase;
-      stringbase += strlen (stringbase) + 1;
+      /* PR 17512: file: 4a1d50c1.  */
+      len = strnlen (stringbase, stringsize);
+      if (len < stringsize)
+       len ++;
+      stringbase += len;
+      stringsize -= len;
       carsyms++;
     }
   *stringbase = 0;
       carsyms++;
     }
   *stringbase = 0;
index 20eef95..3fcbd78 100644 (file)
@@ -152,7 +152,8 @@ DESCRIPTION
        return @var{*ptr} with memory malloc'd by this function.
 
        Return @code{TRUE} if the full section contents is retrieved
        return @var{*ptr} with memory malloc'd by this function.
 
        Return @code{TRUE} if the full section contents is retrieved
-       successfully.
+       successfully.  If the section has no contents then this function
+       returns @code{TRUE} but @var{*ptr} is set to NULL.
 */
 
 bfd_boolean
 */
 
 bfd_boolean
@@ -172,7 +173,10 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
   else
     sz = sec->size;
   if (sz == 0)
   else
     sz = sec->size;
   if (sz == 0)
-    return TRUE;
+    {
+      *ptr = NULL;
+      return TRUE;
+    }
 
   switch (sec->compress_status)
     {
 
   switch (sec->compress_status)
     {
@@ -183,6 +187,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
          if (p == NULL)
            return FALSE;
        }
          if (p == NULL)
            return FALSE;
        }
+
       if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
        {
          if (*ptr != p)
       if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
        {
          if (*ptr != p)
@@ -246,7 +251,9 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
            return FALSE;
          *ptr = p;
        }
            return FALSE;
          *ptr = p;
        }
-      memcpy (p, sec->contents, sz);
+      /* PR 17512; file: 5bc29788.  */
+      if (p != sec->contents)
+       memcpy (p, sec->contents, sz);
       return TRUE;
 
     default:
       return TRUE;
 
     default:
index 6bc2944..25f7e26 100644 (file)
@@ -430,9 +430,13 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 {
   bfd_byte *contents;
   bfd_byte *p;
 {
   bfd_byte *contents;
   bfd_byte *p;
+  bfd_byte *p_end;
   bfd_vma len;
   const char *std_sec;
 
   bfd_vma len;
   const char *std_sec;
 
+  /* PR 17512: file: 2844a11d.  */
+  if (hdr->sh_size == 0)
+    return;
   contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
   if (!contents)
     return;
   contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
   if (!contents)
     return;
@@ -443,11 +447,14 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
       return;
     }
   p = contents;
       return;
     }
   p = contents;
+  p_end = p + hdr->sh_size;
   std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
   std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
+  
   if (*(p++) == 'A')
     {
       len = hdr->sh_size - 1;
   if (*(p++) == 'A')
     {
       len = hdr->sh_size - 1;
-      while (len > 0)
+
+      while (len > 0 && p < p_end - 4)
        {
          unsigned namelen;
          bfd_vma section_len;
        {
          unsigned namelen;
          bfd_vma section_len;
@@ -477,7 +484,7 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
            }
 
          p += namelen;
            }
 
          p += namelen;
-         while (section_len > 0)
+         while (section_len > 0 && p < p_end)
            {
              int tag;
              unsigned int n;
            {
              int tag;
              unsigned int n;
@@ -487,7 +494,10 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 
              tag = read_unsigned_leb128 (abfd, p, &n);
              p += n;
 
              tag = read_unsigned_leb128 (abfd, p, &n);
              p += n;
-             subsection_len = bfd_get_32 (abfd, p);
+             if (p < p_end - 4)
+               subsection_len = bfd_get_32 (abfd, p);
+             else
+               subsection_len = 0;
              p += 4;
              if (subsection_len == 0)
                break;
              p += 4;
              if (subsection_len == 0)
                break;
index 07cb804..405ec33 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -297,13 +297,14 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
       /* Allocate and clear an extra byte at the end, to prevent crashes
         in case the string table is not terminated.  */
       if (shstrtabsize + 1 <= 1
       /* Allocate and clear an extra byte at the end, to prevent crashes
         in case the string table is not terminated.  */
       if (shstrtabsize + 1 <= 1
-         || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
-         || bfd_seek (abfd, offset, SEEK_SET) != 0)
+         || bfd_seek (abfd, offset, SEEK_SET) != 0
+         || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
        shstrtab = NULL;
       else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_file_truncated);
        shstrtab = NULL;
       else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_file_truncated);
+         bfd_release (abfd, shstrtab);
          shstrtab = NULL;
          /* Once we've failed to read it, make sure we don't keep
             trying.  Otherwise, we'll keep allocating space for
          shstrtab = NULL;
          /* Once we've failed to read it, make sure we don't keep
             trying.  Otherwise, we'll keep allocating space for
@@ -332,9 +333,19 @@ bfd_elf_string_from_elf_section (bfd *abfd,
 
   hdr = elf_elfsections (abfd)[shindex];
 
 
   hdr = elf_elfsections (abfd)[shindex];
 
-  if (hdr->contents == NULL
-      && bfd_elf_get_str_section (abfd, shindex) == NULL)
-    return NULL;
+  if (hdr->contents == NULL)
+    {
+      if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
+       {
+         /* PR 17512: file: f057ec89.  */
+         _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
+                             abfd, shindex);
+         return NULL;
+       }
+  
+      if (bfd_elf_get_str_section (abfd, shindex) == NULL)
+       return NULL;
+    }
 
   if (strindex >= hdr->sh_size)
     {
 
   if (strindex >= hdr->sh_size)
     {
@@ -636,6 +647,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                     pointers.  */
                  src = shdr->contents + shdr->sh_size;
                  dest = (Elf_Internal_Group *) (shdr->contents + amt);
                     pointers.  */
                  src = shdr->contents + shdr->sh_size;
                  dest = (Elf_Internal_Group *) (shdr->contents + amt);
+
                  while (1)
                    {
                      unsigned int idx;
                  while (1)
                    {
                      unsigned int idx;
@@ -1253,6 +1265,9 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
       swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
       extdyn = dynbuf;
       swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
       extdyn = dynbuf;
+      /* PR 17512: file: 6f427532.  */
+      if (s->size < extdynsize)
+       goto error_return;
       extdynend = extdyn + s->size;
       /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
          Fix range check.  */
       extdynend = extdyn + s->size;
       /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
          Fix range check.  */
@@ -1607,7 +1622,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
   if (++ nesting > 3)
     {
       /* PR17512: A corrupt ELF binary might contain a recursive group of
   if (++ nesting > 3)
     {
       /* PR17512: A corrupt ELF binary might contain a recursive group of
-        sections, each the string indicies pointing to the next in the
+        sections, with each the string indicies pointing to the next in the
         loop.  Detect this here, by refusing to load a section that we are
         already in the process of loading.  We only trigger this test if
         we have nested at least three sections deep as normal ELF binaries
         loop.  Detect this here, by refusing to load a section that we are
         already in the process of loading.  We only trigger this test if
         we have nested at least three sections deep as normal ELF binaries
@@ -1974,7 +1989,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        else
          p_hdr = &esdt->rel.hdr;
 
        else
          p_hdr = &esdt->rel.hdr;
 
-       BFD_ASSERT (*p_hdr == NULL);
+       /* PR 17512: file: 0b4f81b7.  */
+       if (*p_hdr != NULL)
+         goto fail;
        amt = sizeof (*hdr2);
        hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
        if (hdr2 == NULL)
        amt = sizeof (*hdr2);
        hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
        if (hdr2 == NULL)
@@ -2031,15 +2048,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       if (hdr->contents != NULL)
        {
          Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
       if (hdr->contents != NULL)
        {
          Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
-         unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE;
+         unsigned int n_elt = hdr->sh_size / sizeof (* idx);
          asection *s;
 
          asection *s;
 
+         if (n_elt == 0)
+           goto fail;
          if (idx->flags & GRP_COMDAT)
            hdr->bfd_section->flags
              |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 
          /* We try to keep the same section order as it comes in.  */
          idx += n_elt;
          if (idx->flags & GRP_COMDAT)
            hdr->bfd_section->flags
              |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 
          /* We try to keep the same section order as it comes in.  */
          idx += n_elt;
+
          while (--n_elt != 0)
            {
              --idx;
          while (--n_elt != 0)
            {
              --idx;
index 5c35d65..dcf37b1 100644 (file)
@@ -379,7 +379,9 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
                             abfd, (int) r_type);
       indx = R_386_NONE;
     }
                             abfd, (int) r_type);
       indx = R_386_NONE;
     }
-  BFD_ASSERT (elf_howto_table [indx].type == r_type);
+  /* PR 17512: file: 0f67f69d.  */
+  if (elf_howto_table [indx].type != r_type)
+    return NULL;
   return &elf_howto_table[indx];
 }
 
   return &elf_howto_table[indx];
 }
 
index ec53c3b..d34e18e 100644 (file)
@@ -1501,7 +1501,9 @@ elf_slurp_reloc_table (bfd *abfd,
       rel_hdr2 = d->rela.hdr;
       reloc_count2 = rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0;
 
       rel_hdr2 = d->rela.hdr;
       reloc_count2 = rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0;
 
-      BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+      /* PR 17512: file: 0b4f81b7.  */
+      if (asect->reloc_count != reloc_count + reloc_count2)
+       return FALSE;
       BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset)
                  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
 
       BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset)
                  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
 
index dedfb6a..89e46f3 100644 (file)
@@ -592,6 +592,10 @@ bfd_perform_relocation (bfd *abfd,
       return bfd_reloc_ok;
     }
 
       return bfd_reloc_ok;
     }
 
+  /* PR 17512: file: 0f67f69d.  */
+  if (howto == NULL)
+    return bfd_reloc_undefined;
+
   /* If we are not producing relocatable output, return an error if
      the symbol is not defined.  An undefined weak symbol is
      considered to have a value of zero (SVR4 ABI, p. 4-27).  */
   /* If we are not producing relocatable output, return an error if
      the symbol is not defined.  An undefined weak symbol is
      considered to have a value of zero (SVR4 ABI, p. 4-27).  */
index ecb7c8b..597e52a 100644 (file)
@@ -1,5 +1,22 @@
 2014-12-01  Nick Clifton  <nickc@redhat.com>
 
 2014-12-01  Nick Clifton  <nickc@redhat.com>
 
+       PR binutils/17512
+       * dwarf.h (struct dwarf_section): Add user_data field.
+       * dwarf.c (frame_need_space): Check for an over large register
+       number.
+       (display_debug_frames): Check the return value from
+       frame_need_space.  Check for a CFA expression that is so long the
+       start address wraps around.
+       (debug_displays): Initialise the user_data field.
+       * objdump.c (load_specific_debug_section): Save the BFD section
+       pointer in the user_data field of the dwarf_section structure.
+       (free_debug_section): Update BFD section data when freeing section
+       contents.
+       * readelf.c (load_specific_debug_section): Initialise the
+       user_data field.
+
+2014-12-01  Nick Clifton  <nickc@redhat.com>
+
        PR binutils/17531
        * dwarf.c (process_cu_tu_index): Check for an out of range row
        index.
        PR binutils/17531
        * dwarf.c (process_cu_tu_index): Check for an out of range row
        index.
index 5f953d5..d744929 100644 (file)
@@ -5157,6 +5157,16 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
   if (fc->ncols == 0)
     return -1;
 
   if (fc->ncols == 0)
     return -1;
 
+  /* PR 17512: file: 2844a11d.  */
+  if (fc->ncols > 1024)
+    {
+      error (_("Unfeasibly large register number: %u\n"), reg);
+      fc->ncols = 0;
+      /* FIXME: 1024 is an arbitrary limit.  Increase it if
+        we ever encounter a valid binary that exceeds it.  */
+      return -1;
+    }
+
   fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
                                           sizeof (short int));
   fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
   fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
                                           sizeof (short int));
   fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
@@ -5590,7 +5600,8 @@ display_debug_frames (struct dwarf_section *section,
          mreg = max_regs > 0 ? max_regs - 1 : 0;
          if (mreg < fc->ra)
            mreg = fc->ra;
          mreg = max_regs > 0 ? max_regs - 1 : 0;
          if (mreg < fc->ra)
            mreg = fc->ra;
-         frame_need_space (fc, mreg);
+         if (frame_need_space (fc, mreg) < 0)
+           break;
          if (fc->fde_encoding)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
          if (fc->fde_encoding)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
@@ -5696,7 +5707,11 @@ display_debug_frames (struct dwarf_section *section,
                          mreg = max_regs > 0 ? max_regs - 1 : 0;
                          if (mreg < cie->ra)
                            mreg = cie->ra;
                          mreg = max_regs > 0 ? max_regs - 1 : 0;
                          if (mreg < cie->ra)
                            mreg = cie->ra;
-                         frame_need_space (cie, mreg);
+                         if (frame_need_space (cie, mreg) < 0)
+                           {
+                             warn (_("Invalid max register\n"));
+                             break;
+                           }
                          if (cie->fde_encoding)
                            encoded_ptr_size
                              = size_of_encoded_value (cie->fde_encoding);
                          if (cie->fde_encoding)
                            encoded_ptr_size
                              = size_of_encoded_value (cie->fde_encoding);
@@ -5716,7 +5731,11 @@ display_debug_frames (struct dwarf_section *section,
              fc->ncols = 0;
              fc->col_type = (short int *) xmalloc (sizeof (short int));
              fc->col_offset = (int *) xmalloc (sizeof (int));
              fc->ncols = 0;
              fc->col_type = (short int *) xmalloc (sizeof (short int));
              fc->col_offset = (int *) xmalloc (sizeof (int));
-             frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0);
+             if (frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0) < 0)
+               {
+                 warn (_("Invalid max register\n"));
+                 break;
+               }
              cie = fc;
              fc->augmentation = "";
              fc->fde_encoding = 0;
              cie = fc;
              fc->augmentation = "";
              fc->fde_encoding = 0;
@@ -5739,7 +5758,11 @@ display_debug_frames (struct dwarf_section *section,
              fc->cfa_reg = cie->cfa_reg;
              fc->cfa_offset = cie->cfa_offset;
              fc->ra = cie->ra;
              fc->cfa_reg = cie->cfa_reg;
              fc->cfa_offset = cie->cfa_offset;
              fc->ra = cie->ra;
-             frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0);
+             if (frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0) < 0)
+               {
+                 warn (_("Invalid max register\n"));
+                 break;
+               }
              fc->fde_encoding = cie->fde_encoding;
            }
 
              fc->fde_encoding = cie->fde_encoding;
            }
 
@@ -5857,7 +5880,6 @@ display_debug_frames (struct dwarf_section *section,
                  break;
                case DW_CFA_restore_extended:
                  reg = LEB ();
                  break;
                case DW_CFA_restore_extended:
                  reg = LEB ();
-                 frame_need_space (fc, reg);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
@@ -6176,7 +6198,12 @@ display_debug_frames (struct dwarf_section *section,
                  fc->cfa_reg = rs->cfa_reg;
                  fc->ra = rs->ra;
                  fc->cfa_exp = rs->cfa_exp;
                  fc->cfa_reg = rs->cfa_reg;
                  fc->ra = rs->ra;
                  fc->cfa_exp = rs->cfa_exp;
-                 frame_need_space (fc, rs->ncols - 1);
+                 if (frame_need_space (fc, rs->ncols - 1) < 0)
+                   {
+                     warn (_("Invalid column number in saved frame state"));
+                     fc->ncols = 0;
+                     break;
+                   }
                  memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
                  memcpy (fc->col_offset, rs->col_offset,
                          rs->ncols * sizeof (* rs->col_offset));
                  memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
                  memcpy (fc->col_offset, rs->col_offset,
                          rs->ncols * sizeof (* rs->col_offset));
@@ -6218,7 +6245,7 @@ display_debug_frames (struct dwarf_section *section,
 
            case DW_CFA_def_cfa_expression:
              ul = LEB ();
 
            case DW_CFA_def_cfa_expression:
              ul = LEB ();
-             if (start >= block_end || start + ul > block_end)
+             if (start >= block_end || start + ul > block_end || start + ul < start)
                {
                  printf (_("  DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
                  break;
                {
                  printf (_("  DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
                  break;
@@ -6240,7 +6267,8 @@ display_debug_frames (struct dwarf_section *section,
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              /* PR 17512: file: 069-133014-0.006.  */
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              /* PR 17512: file: 069-133014-0.006.  */
-             if (start >= block_end || start + ul > block_end)
+             /* PR 17512: file: 98c02eb4.  */
+             if (start >= block_end || start + ul > block_end || start + ul < start)
                {
                  printf (_("  DW_CFA_expression: <corrupt len %lu>\n"), ul);
                  break;
                {
                  printf (_("  DW_CFA_expression: <corrupt len %lu>\n"), ul);
                  break;
@@ -6263,7 +6291,7 @@ display_debug_frames (struct dwarf_section *section,
              ul = LEB ();
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              ul = LEB ();
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
-             if (start >= block_end || start + ul > block_end)
+             if (start >= block_end || start + ul > block_end || start + ul < start)
                {
                  printf ("  DW_CFA_val_expression: <corrupt len %lu>\n", ul);
                  break;
                {
                  printf ("  DW_CFA_val_expression: <corrupt len %lu>\n", ul);
                  break;
@@ -7189,76 +7217,76 @@ dwarf_select_sections_all (void)
 
 struct dwarf_section_display debug_displays[] =
 {
 
 struct dwarf_section_display debug_displays[] =
 {
-  { { ".debug_abbrev",     ".zdebug_abbrev",   NULL, NULL, 0, 0, 0 },
+  { { ".debug_abbrev",     ".zdebug_abbrev",   NULL, NULL, 0, 0, 0, NULL },
     display_debug_abbrev,   &do_debug_abbrevs, 0 },
     display_debug_abbrev,   &do_debug_abbrevs, 0 },
-  { { ".debug_aranges",            ".zdebug_aranges",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_aranges",            ".zdebug_aranges",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_aranges,  &do_debug_aranges, 1 },
     display_debug_aranges,  &do_debug_aranges, 1 },
-  { { ".debug_frame",       ".zdebug_frame",   NULL, NULL, 0, 0, 0 },
+  { { ".debug_frame",       ".zdebug_frame",   NULL, NULL, 0, 0, 0, NULL },
     display_debug_frames,   &do_debug_frames,  1 },
     display_debug_frames,   &do_debug_frames,  1 },
-  { { ".debug_info",       ".zdebug_info",     NULL, NULL, 0, 0, abbrev },
+  { { ".debug_info",       ".zdebug_info",     NULL, NULL, 0, 0, abbrev, NULL },
     display_debug_info,            &do_debug_info,     1 },
     display_debug_info,            &do_debug_info,     1 },
-  { { ".debug_line",       ".zdebug_line",     NULL, NULL, 0, 0, 0 },
+  { { ".debug_line",       ".zdebug_line",     NULL, NULL, 0, 0, 0, NULL },
     display_debug_lines,    &do_debug_lines,   1 },
     display_debug_lines,    &do_debug_lines,   1 },
-  { { ".debug_pubnames",    ".zdebug_pubnames",        NULL, NULL, 0, 0, 0 },
+  { { ".debug_pubnames",    ".zdebug_pubnames",        NULL, NULL, 0, 0, 0, NULL },
     display_debug_pubnames, &do_debug_pubnames,        0 },
     display_debug_pubnames, &do_debug_pubnames,        0 },
-  { { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NULL, NULL, 0, 0, 0 },
+  { { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NULL, NULL, 0, 0, 0, NULL },
     display_debug_gnu_pubnames, &do_debug_pubnames, 0 },
     display_debug_gnu_pubnames, &do_debug_pubnames, 0 },
-  { { ".eh_frame",         "",                 NULL, NULL, 0, 0, 0 },
+  { { ".eh_frame",         "",                 NULL, NULL, 0, 0, 0, NULL },
     display_debug_frames,   &do_debug_frames,  1 },
     display_debug_frames,   &do_debug_frames,  1 },
-  { { ".debug_macinfo",            ".zdebug_macinfo",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_macinfo",            ".zdebug_macinfo",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_macinfo,  &do_debug_macinfo, 0 },
     display_debug_macinfo,  &do_debug_macinfo, 0 },
-  { { ".debug_macro",      ".zdebug_macro",    NULL, NULL, 0, 0, 0 },
+  { { ".debug_macro",      ".zdebug_macro",    NULL, NULL, 0, 0, 0, NULL },
     display_debug_macro,    &do_debug_macinfo, 1 },
     display_debug_macro,    &do_debug_macinfo, 1 },
-  { { ".debug_str",        ".zdebug_str",      NULL, NULL, 0, 0, 0 },
+  { { ".debug_str",        ".zdebug_str",      NULL, NULL, 0, 0, 0, NULL },
     display_debug_str,     &do_debug_str,      0 },
     display_debug_str,     &do_debug_str,      0 },
-  { { ".debug_loc",        ".zdebug_loc",      NULL, NULL, 0, 0, 0 },
+  { { ".debug_loc",        ".zdebug_loc",      NULL, NULL, 0, 0, 0, NULL },
     display_debug_loc,     &do_debug_loc,      1 },
     display_debug_loc,     &do_debug_loc,      1 },
-  { { ".debug_pubtypes",    ".zdebug_pubtypes",        NULL, NULL, 0, 0, 0 },
+  { { ".debug_pubtypes",    ".zdebug_pubtypes",        NULL, NULL, 0, 0, 0, NULL },
     display_debug_pubnames, &do_debug_pubtypes,        0 },
     display_debug_pubnames, &do_debug_pubtypes,        0 },
-  { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NULL, NULL, 0, 0, 0 },
+  { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NULL, NULL, 0, 0, 0, NULL },
     display_debug_gnu_pubnames, &do_debug_pubtypes, 0 },
     display_debug_gnu_pubnames, &do_debug_pubtypes, 0 },
-  { { ".debug_ranges",     ".zdebug_ranges",   NULL, NULL, 0, 0, 0 },
+  { { ".debug_ranges",     ".zdebug_ranges",   NULL, NULL, 0, 0, 0, NULL },
     display_debug_ranges,   &do_debug_ranges,  1 },
     display_debug_ranges,   &do_debug_ranges,  1 },
-  { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, 0 },
+  { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, 0, NULL },
     display_debug_not_supported, NULL,         0 },
     display_debug_not_supported, NULL,         0 },
-  { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, 0 },
+  { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, 0, NULL },
     display_debug_not_supported, NULL,         0 },
     display_debug_not_supported, NULL,         0 },
-  { { ".debug_types",      ".zdebug_types",    NULL, NULL, 0, 0, abbrev },
+  { { ".debug_types",      ".zdebug_types",    NULL, NULL, 0, 0, abbrev, NULL },
     display_debug_types,    &do_debug_info,    1 },
     display_debug_types,    &do_debug_info,    1 },
-  { { ".debug_weaknames",   ".zdebug_weaknames", NULL, NULL, 0, 0, 0 },
+  { { ".debug_weaknames",   ".zdebug_weaknames", NULL, NULL, 0, 0, 0, NULL },
     display_debug_not_supported, NULL,         0 },
     display_debug_not_supported, NULL,         0 },
-  { { ".gdb_index",        "",                 NULL, NULL, 0, 0, 0 },
+  { { ".gdb_index",        "",                 NULL, NULL, 0, 0, 0, NULL },
     display_gdb_index,      &do_gdb_index,     0 },
     display_gdb_index,      &do_gdb_index,     0 },
-  { { ".trace_info",       "",                 NULL, NULL, 0, 0, trace_abbrev },
+  { { ".trace_info",       "",                 NULL, NULL, 0, 0, trace_abbrev, NULL },
     display_trace_info,            &do_trace_info,     1 },
     display_trace_info,            &do_trace_info,     1 },
-  { { ".trace_abbrev",     "",                 NULL, NULL, 0, 0, 0 },
+  { { ".trace_abbrev",     "",                 NULL, NULL, 0, 0, 0, NULL },
     display_debug_abbrev,   &do_trace_abbrevs, 0 },
     display_debug_abbrev,   &do_trace_abbrevs, 0 },
-  { { ".trace_aranges",            "",                 NULL, NULL, 0, 0, 0 },
+  { { ".trace_aranges",            "",                 NULL, NULL, 0, 0, 0, NULL },
     display_debug_aranges,  &do_trace_aranges, 0 },
     display_debug_aranges,  &do_trace_aranges, 0 },
-  { { ".debug_info.dwo",    ".zdebug_info.dwo",        NULL, NULL, 0, 0, abbrev_dwo },
+  { { ".debug_info.dwo",    ".zdebug_info.dwo",        NULL, NULL, 0, 0, abbrev_dwo, NULL },
     display_debug_info,            &do_debug_info,     1 },
     display_debug_info,            &do_debug_info,     1 },
-  { { ".debug_abbrev.dwo",  ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_abbrev.dwo",  ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_abbrev,   &do_debug_abbrevs, 0 },
     display_debug_abbrev,   &do_debug_abbrevs, 0 },
-  { { ".debug_types.dwo",   ".zdebug_types.dwo", NULL, NULL, 0, 0, abbrev_dwo },
+  { { ".debug_types.dwo",   ".zdebug_types.dwo", NULL, NULL, 0, 0, abbrev_dwo, NULL },
     display_debug_types,    &do_debug_info,    1 },
     display_debug_types,    &do_debug_info,    1 },
-  { { ".debug_line.dwo",    ".zdebug_line.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_line.dwo",    ".zdebug_line.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_lines,    &do_debug_lines,   1 },
     display_debug_lines,    &do_debug_lines,   1 },
-  { { ".debug_loc.dwo",            ".zdebug_loc.dwo",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_loc.dwo",            ".zdebug_loc.dwo",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_loc,     &do_debug_loc,      1 },
     display_debug_loc,     &do_debug_loc,      1 },
-  { { ".debug_macro.dwo",   ".zdebug_macro.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_macro.dwo",   ".zdebug_macro.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_macro,    &do_debug_macinfo, 1 },
     display_debug_macro,    &do_debug_macinfo, 1 },
-  { { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_macinfo,  &do_debug_macinfo, 0 },
     display_debug_macinfo,  &do_debug_macinfo, 0 },
-  { { ".debug_str.dwo",     ".zdebug_str.dwo",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_str.dwo",     ".zdebug_str.dwo",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_str,      &do_debug_str,     1 },
     display_debug_str,      &do_debug_str,     1 },
-  { { ".debug_str_offsets", ".zdebug_str_offsets", NULL, NULL, 0, 0, 0 },
+  { { ".debug_str_offsets", ".zdebug_str_offsets", NULL, NULL, 0, 0, 0, NULL },
     display_debug_str_offsets, NULL,           0 },
     display_debug_str_offsets, NULL,           0 },
-  { { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_str_offsets, NULL,           0 },
     display_debug_str_offsets, NULL,           0 },
-  { { ".debug_addr",       ".zdebug_addr",     NULL, NULL, 0, 0, 0 },
+  { { ".debug_addr",       ".zdebug_addr",     NULL, NULL, 0, 0, 0, NULL },
     display_debug_addr,     &do_debug_addr,    1 },
     display_debug_addr,     &do_debug_addr,    1 },
-  { { ".debug_cu_index",    "",                        NULL, NULL, 0, 0, 0 },
+  { { ".debug_cu_index",    "",                        NULL, NULL, 0, 0, 0, NULL },
     display_cu_index,       &do_debug_cu_index,        0 },
     display_cu_index,       &do_debug_cu_index,        0 },
-  { { ".debug_tu_index",    "",                        NULL, NULL, 0, 0, 0 },
+  { { ".debug_tu_index",    "",                        NULL, NULL, 0, 0, 0, NULL },
     display_cu_index,       &do_debug_cu_index,        0 },
 };
     display_cu_index,       &do_debug_cu_index,        0 },
 };
index 124d9d6..bd62892 100644 (file)
@@ -164,6 +164,8 @@ struct dwarf_section
   dwarf_vma address;
   dwarf_size_type size;
   enum dwarf_section_display_enum abbrev_sec;
   dwarf_vma address;
   dwarf_size_type size;
   enum dwarf_section_display_enum abbrev_sec;
+  /* A spare field for random use.  */
+  void *user_data;
 };
 
 /* A structure containing the name of a debug section
 };
 
 /* A structure containing the name of a debug section
index fdfa602..b13bf00 100644 (file)
@@ -2280,6 +2280,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
   section->address = bfd_get_section_vma (abfd, sec);
   section->size = bfd_get_section_size (sec);
   section->start = NULL;
   section->address = bfd_get_section_vma (abfd, sec);
   section->size = bfd_get_section_size (sec);
   section->start = NULL;
+  section->user_data = sec;
   ret = bfd_get_full_section_contents (abfd, sec, &section->start);
 
   if (! ret)
   ret = bfd_get_full_section_contents (abfd, sec, &section->start);
 
   if (! ret)
@@ -2346,6 +2347,22 @@ free_debug_section (enum dwarf_section_display_enum debug)
   if (section->start == NULL)
     return;
 
   if (section->start == NULL)
     return;
 
+  /* PR 17512: file: 0f67f69d.  */
+  if (section->user_data != NULL)
+    {
+      asection * sec = (asection *) section->user_data;
+
+      /* If we are freeing contents that are also pointed to by the BFD
+        library's section structure then make sure to update those pointers
+        too.  Otherwise, the next time we try to load data for this section
+        we can end up using a stale pointer.  */
+      if (section->start == sec->contents)
+       {
+         sec->contents = NULL;
+         sec->flags &= ~ SEC_IN_MEMORY;
+       }
+    }
+
   free ((char *) section->start);
   section->start = NULL;
   section->address = 0;
   free ((char *) section->start);
   section->start = NULL;
   section->address = 0;
index 4e16bd6..2004752 100644 (file)
@@ -11713,6 +11713,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
 
   snprintf (buf, sizeof (buf), _("%s section data"), section->name);
   section->address = sec->sh_addr;
 
   snprintf (buf, sizeof (buf), _("%s section data"), section->name);
   section->address = sec->sh_addr;
+  section->user_data = NULL;
   section->start = (unsigned char *) get_data (NULL, (FILE *) file,
                                                sec->sh_offset, 1,
                                                sec->sh_size, buf);
   section->start = (unsigned char *) get_data (NULL, (FILE *) file,
                                                sec->sh_offset, 1,
                                                sec->sh_size, buf);