]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix undefined arithmetic operations detected by -fsanitize=undefined when running...
authorNick Clifton <nickc@redhat.com>
Thu, 26 Feb 2015 14:21:54 +0000 (14:21 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 26 Feb 2015 14:23:27 +0000 (14:23 +0000)
PR binutils/17512
* dwarf.c (display_debug_loc): Pacify the undefined behaviour
sanitizer by simplifying address difference calculation.
(struct Frame_Chunk): Change type of cfa_offset to dwarf_vma in
order to avoid arithmetic overflows.
(frame_display_row): Cast cfa_offset before printing it.
(display_debug_frames): Likewise.
Check for an unexpected segment size.
Chnage type of 'l' local to dwarf_vma and cast it back to an int
when printing.
(process_cu_tu_index): Tighten check for an invalid ncols value.
* readelf.c (process_corefile_note_segment): Check for
inote.descdata extending beyond the end of the section.
(process_v850_notes): Likewise.

binutils/ChangeLog
binutils/dwarf.c
binutils/readelf.c

index 8657b1d256bdfc8fff19ded3b41ca9e6ed53637f..3a42b724de9a51a1b94d6c0c2c2d1491a4ade838 100644 (file)
@@ -4,6 +4,20 @@
        * resrc.c (write_rc_messagetable): Tighten check for invalid
        message lengths.
 
+       * dwarf.c (display_debug_loc): Pacify the undefined behaviour
+       sanitizer by simplifying address difference calculation.
+       (struct Frame_Chunk): Change type of cfa_offset to dwarf_vma in
+       order to avoid arithmetic overflows.
+       (frame_display_row): Cast cfa_offset before printing it.
+       (display_debug_frames): Likewise.
+       Check for an unexpected segment size.
+       Chnage type of 'l' local to dwarf_vma and cast it back to an int
+       when printing.
+       (process_cu_tu_index): Tighten check for an invalid ncols value.
+       * readelf.c (process_corefile_note_segment): Check for
+       inote.descdata extending beyond the end of the section.
+       (process_v850_notes): Likewise.
+
 2015-02-26  Terry Guo  <terry.guo@arm.com>
 
        * readelf.c (arm_attr_tag_ABI_HardFP_use): Update how we
index 272b41f9289e855d6319b6cabba0afb8e047cff6..588414081a3078a3c6b82dd86b1e7b5bd38ebefd 100644 (file)
@@ -4719,11 +4719,11 @@ display_debug_loc (struct dwarf_section *section, void *file)
              if (start < next)
                warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
                      (unsigned long) (start - section_begin),
-                     (unsigned long) (next - section_begin));
+                     (unsigned long) offset);
              else if (start > next)
                warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_loc section.\n"),
                      (unsigned long) (start - section_begin),
-                     (unsigned long) (next - section_begin));
+                     (unsigned long) offset);
            }
          start = next;
 
@@ -5244,7 +5244,7 @@ typedef struct Frame_Chunk
   dwarf_vma pc_begin;
   dwarf_vma pc_range;
   int cfa_reg;
-  int cfa_offset;
+  dwarf_vma cfa_offset;
   unsigned int ra;
   unsigned char fde_encoding;
   unsigned char cfa_exp;
@@ -5481,7 +5481,7 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_reg
   if (fc->cfa_exp)
     strcpy (tmp, "exp");
   else
-    sprintf (tmp, "%s%+d", regname (fc->cfa_reg, 1), fc->cfa_offset);
+    sprintf (tmp, "%s%+d", regname (fc->cfa_reg, 1), (int) fc->cfa_offset);
   printf ("%-8s ", tmp);
 
   for (r = 0; r < fc->ncols; r++)
@@ -5921,7 +5921,15 @@ display_debug_frames (struct dwarf_section *section,
 
          segment_selector = 0;
          if (fc->segment_size)
-           SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
+           {
+             if (fc->segment_size > sizeof (segment_selector))
+               {
+                 /* PR 17512: file: 9e196b3e.  */
+                 warn (_("Probably corrupt segment size: %d - using 4 instead\n"), fc->segment_size);
+                 fc->segment_size = 4;
+               }
+             SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
+           }
 
          fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section, end);
 
@@ -6123,7 +6131,7 @@ display_debug_frames (struct dwarf_section *section,
          unsigned char * tmp;
          unsigned op, opa;
          unsigned long ul, reg, roffs;
-         long l;
+         dwarf_vma l;
          dwarf_vma ofs;
          dwarf_vma vma;
          const char *reg_prefix = "";
@@ -6375,7 +6383,7 @@ display_debug_frames (struct dwarf_section *section,
              fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa: %s ofs %d\n",
-                       regname (fc->cfa_reg, 0), fc->cfa_offset);
+                       regname (fc->cfa_reg, 0), (int) fc->cfa_offset);
              break;
 
            case DW_CFA_def_cfa_register:
@@ -6389,7 +6397,7 @@ display_debug_frames (struct dwarf_section *section,
            case DW_CFA_def_cfa_offset:
              fc->cfa_offset = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
+               printf ("  DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
              break;
 
            case DW_CFA_nop:
@@ -6473,7 +6481,7 @@ display_debug_frames (struct dwarf_section *section,
              if (! do_debug_frames_interp || *reg_prefix != '\0')
                printf ("  DW_CFA_offset_extended_sf: %s%s at cfa%+ld\n",
                        reg_prefix, regname (reg, 0),
-                       l * fc->data_factor);
+                       (long)(l * fc->data_factor));
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_offset;
@@ -6489,7 +6497,7 @@ display_debug_frames (struct dwarf_section *section,
              if (! do_debug_frames_interp || *reg_prefix != '\0')
                printf ("  DW_CFA_val_offset_sf: %s%s at cfa%+ld\n",
                        reg_prefix, regname (reg, 0),
-                       l * fc->data_factor);
+                       (long)(l * fc->data_factor));
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_val_offset;
@@ -6504,14 +6512,14 @@ display_debug_frames (struct dwarf_section *section,
              fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_sf: %s ofs %d\n",
-                       regname (fc->cfa_reg, 0), fc->cfa_offset);
+                       regname (fc->cfa_reg, 0), (int) fc->cfa_offset);
              break;
 
            case DW_CFA_def_cfa_offset_sf:
              fc->cfa_offset = SLEB ();
-             fc->cfa_offset = fc->cfa_offset * fc->data_factor;
+             fc->cfa_offset *= fc->data_factor;
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
+               printf ("  DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
              break;
 
            case DW_CFA_MIPS_advance_loc8:
@@ -6546,7 +6554,7 @@ display_debug_frames (struct dwarf_section *section,
              if (! do_debug_frames_interp || *reg_prefix != '\0')
                printf ("  DW_CFA_GNU_negative_offset_extended: %s%s at cfa%+ld\n",
                        reg_prefix, regname (reg, 0),
-                       l * fc->data_factor);
+                       (long)(l * fc->data_factor));
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_offset;
@@ -7026,7 +7034,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
 
       /* PR 17531: file: 0dd159bf.
         Check for wraparound with an overlarge ncols value.  */
-      if ((unsigned int) ((poffsets - ppool) / 4) != ncols)
+      if (poffsets < ppool || (unsigned int) ((poffsets - ppool) / 4) != ncols)
        {
          warn (_("Overlarge number of columns: %x\n"), ncols);
          return 0;
index da616b382bef9e3a1cbee18527091c0800bec9da..06fa8d5ad32da499144e76b771ad5974e30fed62 100644 (file)
@@ -15205,6 +15205,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
 {
   Elf_External_Note * pnotes;
   Elf_External_Note * external;
+  char * end;
   int res = 1;
 
   if (length <= 0)
@@ -15221,13 +15222,14 @@ 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"));
 
-  while ((char *) external < (char *) pnotes + length)
+  end = (char *) pnotes + length;
+  while ((char *) external < end)
     {
       Elf_Internal_Note inote;
       size_t min_notesz;
       char *next;
       char * temp = NULL;
-      size_t data_remaining = ((char *) pnotes + length) - (char *) external;
+      size_t data_remaining = end - (char *) external;
 
       if (!is_ia64_vms ())
        {
@@ -15246,12 +15248,13 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
          inote.descsz   = BYTE_GET (external->descsz);
          inote.descdata = inote.namedata + align_power (inote.namesz, 2);
          /* PR 17531: file: 3443835e.  */
-         if (inote.descdata < (char *) pnotes)
+         if (inote.descdata < (char *) pnotes || inote.descdata > end)
            {
              warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
              inote.descdata = inote.namedata;
              inote.namesz   = 0;
            }
          inote.descpos  = offset + (inote.descdata - (char *) pnotes);
          next = inote.descdata + align_power (inote.descsz, 2);
        }
@@ -15358,6 +15361,7 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
 {
   Elf_External_Note * pnotes;
   Elf_External_Note * external;
+  char * end;
   int res = 1;
 
   if (length <= 0)
@@ -15369,11 +15373,12 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
     return 0;
 
   external = pnotes;
+  end = (char*) pnotes + length;
 
   printf (_("\nDisplaying contents of Renesas V850 notes section at offset 0x%lx with length 0x%lx:\n"),
          (unsigned long) offset, (unsigned long) length);
 
-  while (external < (Elf_External_Note *) ((char *) pnotes + length))
+  while ((char *) external + sizeof (Elf_External_Note) < end)
     {
       Elf_External_Note * next;
       Elf_Internal_Note inote;
@@ -15385,9 +15390,16 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
       inote.descdata = inote.namedata + align_power (inote.namesz, 2);
       inote.descpos  = offset + (inote.descdata - (char *) pnotes);
 
+      if (inote.descdata < (char *) pnotes || inote.descdata >= end)
+       {
+         warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
+         inote.descdata = inote.namedata;
+         inote.namesz   = 0;
+       }
+
       next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
 
-      if (   ((char *) next > ((char *) pnotes) + length)
+      if (   ((char *) next > end)
          || ((char *) next <  (char *) pnotes))
        {
          warn (_("corrupt descsz found in note at offset 0x%lx\n"),
@@ -15400,7 +15412,7 @@ process_v850_notes (FILE * file, bfd_vma offset, bfd_vma length)
       external = next;
 
       /* Prevent out-of-bounds indexing.  */
-      if (   inote.namedata + inote.namesz > (char *) pnotes + length
+      if (   inote.namedata + inote.namesz > end
          || inote.namedata + inote.namesz < inote.namedata)
         {
           warn (_("corrupt namesz found in note at offset 0x%lx\n"),