Fix memory access violations triggered by running objdump compiled with out-of-bounds...
authorNick Clifton <nickc@redhat.com>
Tue, 10 Feb 2015 14:11:00 +0000 (14:11 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 10 Feb 2015 14:11:00 +0000 (14:11 +0000)
PR binutils/17512
* dwarf.c (eh_addr_size): Use an unsigned type.
(size_of_encoded_value): Return an unsigned type.
(read_leb128): Break if the shift becomes too big.
(process_extended_line_op): Do not read the address if the length
is too long.
(read_cie): Warn and fail if the pointer size or segment size are
too big.
* dwarf.h (DWARF2_External_LineInfo): Delete unused and incorrect
structure definition.
(DWARF2_External_PubNames): Likewise.
(DWARF2_External_CompUnit): Likewise.
(DWARF2_External_ARange): Likewise.
(DWARF2_Internal_LineInfo): Use dwarf_vma type for
li_prologue_length.
(eh_addr_size): Update prototype.

* coffcode.h (styp_to_sec_flags): Use an unsigned long type to
hold the flag bits.
* peXXigen.c (pe_print_reloc): Use unsigned types to hold the
size and number of relocs.
(pe_print_debugdata): Use a 32-bit aligned buffer to store the
codeview record.
* versados.c (process_otr): Check the esdid value before using it
to access the EDATA.

bfd/ChangeLog
bfd/coffcode.h
bfd/peXXigen.c
bfd/versados.c
binutils/ChangeLog
binutils/dwarf.c
binutils/dwarf.h

index 650e8ee..d5b50b7 100644 (file)
@@ -1,3 +1,15 @@
+2015-02-10  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/17512
+       * coffcode.h (styp_to_sec_flags): Use an unsigned long type to
+       hold the flag bits.
+       * peXXigen.c (pe_print_reloc): Use unsigned types to hold the
+       size and number of relocs.
+       (pe_print_debugdata): Use a 32-bit aligned buffer to store the
+       codeview record.
+       * versados.c (process_otr): Check the esdid value before using it
+       to access the EDATA.
+
 2015-02-09  Ed Maste  <emaste@freebsd.org>
 
        * elf32-i386.c (elf_i386_get_plt_sym_val): Avoid incrementing
index 76e5873..0ac4ce0 100644 (file)
@@ -1169,7 +1169,7 @@ styp_to_sec_flags (bfd *abfd,
                   flagword *flags_ptr)
 {
   struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
-  long styp_flags = internal_s->s_flags;
+  unsigned long styp_flags = internal_s->s_flags;
   flagword sec_flags;
   bfd_boolean result = TRUE;
   bfd_boolean is_dbg = FALSE;
@@ -1192,7 +1192,7 @@ styp_to_sec_flags (bfd *abfd,
   /* Process each flag bit in styp_flags in turn.  */
   while (styp_flags)
     {
-      long flag = styp_flags & - styp_flags;
+      unsigned long flag = styp_flags & - styp_flags;
       char * unhandled = NULL;
 
       styp_flags &= ~ flag;
index 9feab3b..a7e9f04 100644 (file)
@@ -1151,7 +1151,7 @@ _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length
   /* Ensure null termination of filename.  */
   buffer[256] = '\0';
 
-  cvinfo->CVSignature = H_GET_32(abfd, buffer);
+  cvinfo->CVSignature = H_GET_32 (abfd, buffer);
   cvinfo->Age = 0;
 
   if ((cvinfo->CVSignature == CVINFO_PDB70_CVSIGNATURE)
@@ -2216,7 +2216,7 @@ pe_print_reloc (bfd * abfd, void * vfile)
     {
       int j;
       bfd_vma virtual_address;
-      long number, size;
+      unsigned long number, size;
       bfd_byte *chunk_end;
 
       /* The .reloc section is a sequence of blocks, with a header consisting
@@ -2231,7 +2231,7 @@ pe_print_reloc (bfd * abfd, void * vfile)
 
       fprintf (file,
               _("\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"),
-              (unsigned long) virtual_address, size, (unsigned long) size, number);
+              (unsigned long) virtual_address, size, size, number);
 
       chunk_end = p + size;
       if (chunk_end > end)
@@ -2674,7 +2674,11 @@ pe_print_debugdata (bfd * abfd, void * vfile)
       if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW)
         {
           char signature[CV_INFO_SIGNATURE_LENGTH * 2 + 1];
-          char buffer[256 + 1];
+         /* PR 17512: file: 065-29434-0.001:0.1
+            We need to use a 32-bit aligned buffer
+            to safely read in a codeview record.  */
+          char buffer[256 + 1] ATTRIBUTE_ALIGNED_ALIGNOF (CODEVIEW_INFO);
+
           CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
 
           /* The debug entry doesn't have to have to be in a section,
index 2540314..93a90a7 100644 (file)
@@ -373,7 +373,7 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass)
   | (otr->map[2] << 8)
   | (otr->map[3] << 0);
 
-  struct esdid *esdid = &EDATA (abfd, otr->esdid - 1);
+  struct esdid *esdid;
   unsigned char *contents;
   bfd_boolean need_contents = FALSE;
   unsigned int dst_idx;
@@ -382,6 +382,7 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass)
   if (otr->esdid == 0)
     return;
   
+  esdid = &EDATA (abfd, otr->esdid - 1);
   contents = esdid->contents;
   dst_idx = esdid->pc;
   
index 01c4634..93cab73 100644 (file)
@@ -1,3 +1,22 @@
+2015-02-10  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/17512
+       * dwarf.c (eh_addr_size): Use an unsigned type.
+       (size_of_encoded_value): Return an unsigned type.
+       (read_leb128): Break if the shift becomes too big.
+       (process_extended_line_op): Do not read the address if the length
+       is too long.
+       (read_cie): Warn and fail if the pointer size or segment size are
+       too big.
+       * dwarf.h (DWARF2_External_LineInfo): Delete unused and incorrect
+       structure definition.
+       (DWARF2_External_PubNames): Likewise.
+       (DWARF2_External_CompUnit): Likewise.
+       (DWARF2_External_ARange): Likewise.
+       (DWARF2_Internal_LineInfo): Use dwarf_vma type for
+       li_prologue_length.
+       (eh_addr_size): Update prototype.
+
 2015-02-09  Mark Wielaard  <mjw@redhat.com>
 
        * dwarf.c (read_and_display_attr_value): Handle DW_LANG_Fortran03
index e93a757..9daf315 100644 (file)
@@ -44,7 +44,7 @@ static debug_info *debug_information = NULL;
    that the .debug_info section could not be loaded/parsed.  */
 #define DEBUG_INFO_UNAVAILABLE  (unsigned int) -1
 
-int eh_addr_size;
+unsigned int eh_addr_size;
 
 int do_debug_info;
 int do_debug_abbrevs;
@@ -105,7 +105,7 @@ static void load_cu_tu_indexes (void *file);
 #define FLAG_DEBUG_LINES_RAW    1
 #define FLAG_DEBUG_LINES_DECODED 2
 
-static int
+static unsigned int
 size_of_encoded_value (int encoding)
 {
   switch (encoding & 0x7)
@@ -281,6 +281,11 @@ read_leb128 (unsigned char *data,
       shift += 7;
       if ((byte & 0x80) == 0)
        break;
+
+      /* PR 17512: file: 0ca183b8.
+        FIXME: Should we signal this error somehow ?  */
+      if (shift >= sizeof (result))
+       break;
     }
 
   if (length_return != NULL)
@@ -446,9 +451,13 @@ process_extended_line_op (unsigned char * data,
     case DW_LNE_set_address:
       /* PR 17512: file: 002-100480-0.004.  */
       if (len - bytes_read - 1 > 8)
-       warn (_("Length (%d) of DW_LNE_set_address op is too long\n"),
-             len - bytes_read - 1);
-      SAFE_BYTE_GET (adr, data, len - bytes_read - 1, end);
+       {
+         warn (_("Length (%d) of DW_LNE_set_address op is too long\n"),
+               len - bytes_read - 1);
+         adr = 0;
+       }
+      else
+       SAFE_BYTE_GET (adr, data, len - bytes_read - 1, end);
       printf (_("set Address to 0x%s\n"), dwarf_vmatoa ("x", adr));
       state_machine_regs.address = adr;
       state_machine_regs.op_index = 0;
@@ -2860,7 +2869,7 @@ display_debug_lines_raw (struct dwarf_section *section,
          printf (_("  Offset:                      0x%lx\n"), (long)(data - start));
          printf (_("  Length:                      %ld\n"), (long) linfo.li_length);
          printf (_("  DWARF Version:               %d\n"), linfo.li_version);
-         printf (_("  Prologue Length:             %d\n"), linfo.li_prologue_length);
+         printf (_("  Prologue Length:             %d\n"), (int) linfo.li_prologue_length);
          printf (_("  Minimum Instruction Length:  %d\n"), linfo.li_min_insn_length);
          if (linfo.li_version >= 4)
            printf (_("  Maximum Ops per Instruction: %d\n"), linfo.li_max_ops_per_insn);
@@ -2875,7 +2884,7 @@ display_debug_lines_raw (struct dwarf_section *section,
              warn (_("Line range of 0 is invalid, using 1 instead\n"));
              linfo.li_line_range = 1;
            }
-         
+
          reset_state_machine (linfo.li_default_is_stmt);
 
          /* Display the contents of the Opcodes table.  */
@@ -5542,7 +5551,20 @@ read_cie (unsigned char *start, unsigned char *end,
   if (version >= 4)
     {
       GET (fc->ptr_size, 1);
+      if (fc->ptr_size < 1 || fc->ptr_size > 8)
+       {
+         warn (_("Invalid pointer size (%d) in CIE data\n"), fc->ptr_size);
+         return end;
+       }
+
       GET (fc->segment_size, 1);
+      /* PR 17512: file: e99d2804.  */
+      if (fc->segment_size > 8 || fc->segment_size + fc->ptr_size > 8)
+       {
+         warn (_("Invalid segment size (%d) in CIE data\n"), fc->segment_size);
+         return end;
+       }
+
       eh_addr_size = fc->ptr_size;
     }
   else
@@ -5634,7 +5656,7 @@ display_debug_frames (struct dwarf_section *section,
   unsigned int length_return;
   unsigned int max_regs = 0;
   const char *bad_reg = _("bad register: ");
-  int saved_eh_addr_size = eh_addr_size;
+  unsigned int saved_eh_addr_size = eh_addr_size;
 
   printf (_("Contents of the %s section:\n"), section->name);
 
index 54dcbc7..45f9927 100644 (file)
@@ -25,22 +25,9 @@ typedef unsigned HOST_WIDEST_INT  dwarf_size_type;
 /* Structure found in the .debug_line section.  */
 typedef struct
 {
-  unsigned char li_length          [4];
-  unsigned char li_version         [2];
-  unsigned char li_prologue_length [4];
-  unsigned char li_min_insn_length [1];
-  unsigned char li_default_is_stmt [1];
-  unsigned char li_line_base       [1];
-  unsigned char li_line_range      [1];
-  unsigned char li_opcode_base     [1];
-}
-DWARF2_External_LineInfo;
-
-typedef struct
-{
   dwarf_vma     li_length;
   unsigned short li_version;
-  unsigned int   li_prologue_length;
+  dwarf_vma      li_prologue_length;
   unsigned char  li_min_insn_length;
   unsigned char  li_max_ops_per_insn;
   unsigned char  li_default_is_stmt;
@@ -53,15 +40,6 @@ DWARF2_Internal_LineInfo;
 /* Structure found in .debug_pubnames section.  */
 typedef struct
 {
-  unsigned char pn_length  [4];
-  unsigned char pn_version [2];
-  unsigned char pn_offset  [4];
-  unsigned char pn_size    [4];
-}
-DWARF2_External_PubNames;
-
-typedef struct
-{
   dwarf_vma     pn_length;
   unsigned short pn_version;
   dwarf_vma     pn_offset;
@@ -72,15 +50,6 @@ DWARF2_Internal_PubNames;
 /* Structure found in .debug_info section.  */
 typedef struct
 {
-  unsigned char  cu_length        [4];
-  unsigned char  cu_version       [2];
-  unsigned char  cu_abbrev_offset [4];
-  unsigned char  cu_pointer_size  [1];
-}
-DWARF2_External_CompUnit;
-
-typedef struct
-{
   dwarf_vma     cu_length;
   unsigned short cu_version;
   dwarf_vma     cu_abbrev_offset;
@@ -88,16 +57,7 @@ typedef struct
 }
 DWARF2_Internal_CompUnit;
 
-typedef struct
-{
-  unsigned char  ar_length       [4];
-  unsigned char  ar_version      [2];
-  unsigned char  ar_info_offset  [4];
-  unsigned char  ar_pointer_size [1];
-  unsigned char  ar_segment_size [1];
-}
-DWARF2_External_ARange;
-
+/* Structure found in .debug_aranges section.  */
 typedef struct
 {
   dwarf_vma     ar_length;
@@ -207,7 +167,7 @@ typedef struct
 }
 debug_info;
 
-extern int eh_addr_size;
+extern unsigned int eh_addr_size;
 
 extern int do_debug_info;
 extern int do_debug_abbrevs;