Sanity check loc_offsets index
authorAlan Modra <amodra@gmail.com>
Thu, 4 Aug 2022 12:13:22 +0000 (21:43 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 5 Aug 2022 11:18:29 +0000 (20:48 +0930)
Fixes a segfault found by the fuzzers.

* dwarf.c (fetch_indexed_value): Return -1 on error.
(read_and_display_attr_value): Don't display string when
fetch_indexed_value returns an error.  Sanity check loc_offsets
index.

binutils/dwarf.c

index 6574b45ffdf8e4d52955b2f8f6b397c258dce515..d862e16388ba528bcfbfff675dd90e5ea598abcb 100644 (file)
@@ -779,7 +779,7 @@ fetch_indexed_addr (dwarf_vma offset, uint32_t num_bytes)
 
 /* Fetch a value from a debug section that has been indexed by
    something in another section (eg DW_FORM_loclistx or DW_FORM_rnglistx).
-   Returns 0 if the value could not be found.  */
+   Returns -1 if the value could not be found.  */
 
 static dwarf_vma
 fetch_indexed_value (dwarf_vma idx,
@@ -791,7 +791,7 @@ fetch_indexed_value (dwarf_vma idx,
   if (section->start == NULL)
     {
       warn (_("Unable to locate %s section\n"), section->uncompressed_name);
-      return 0;
+      return -1;
     }
 
   uint32_t pointer_size, bias;
@@ -820,7 +820,7 @@ fetch_indexed_value (dwarf_vma idx,
     {
       warn (_("Offset into section %s too big: 0x%s\n"),
            section->name, dwarf_vmatoa ("x", offset));
-      return 0;
+      return -1;
     }
 
   return byte_get (section->start + offset, pointer_size);
@@ -2782,7 +2782,8 @@ read_and_display_attr_value (unsigned long           attribute,
              if (dwo)
                {
                  idx = fetch_indexed_value (uvalue, loclists_dwo, 0);
-                 idx += (offset_size == 8) ? 20 : 12;
+                 if (idx != (dwarf_vma) -1)
+                   idx += (offset_size == 8) ? 20 : 12;
                }
              else if (debug_info_p == NULL)
                {
@@ -2795,7 +2796,13 @@ read_and_display_attr_value (unsigned long           attribute,
                       idx += debug_info_p->loclists_base;
                      Fortunately we already have that sum cached in the
                      loc_offsets array.  */
-                 idx = debug_info_p->loc_offsets [uvalue];
+                 if (uvalue < debug_info_p->num_loc_offsets)
+                   idx = debug_info_p->loc_offsets [uvalue];
+                 else
+                   {
+                     warn (_("loc_offset %" PRIu64 " too big\n"), uvalue);
+                     idx = -1;
+                   }
                }
            }
          else if (form == DW_FORM_rnglistx)
@@ -2803,7 +2810,8 @@ read_and_display_attr_value (unsigned long           attribute,
              if (dwo)
                {
                  idx = fetch_indexed_value (uvalue, rnglists_dwo, 0);
-                 idx += (offset_size == 8) ? 20 : 12;
+                 if (idx != (dwarf_vma) -1)
+                   idx += (offset_size == 8) ? 20 : 12;
                }
              else
                {
@@ -2814,7 +2822,8 @@ read_and_display_attr_value (unsigned long           attribute,
                  /* We do not have a cached value this time, so we perform the
                     computation manually.  */
                  idx = fetch_indexed_value (uvalue, rnglists, base);
-                 idx += base;
+                 if (idx != (dwarf_vma) -1)
+                   idx += base;
                }
            }
          else
@@ -2831,9 +2840,10 @@ read_and_display_attr_value (unsigned long           attribute,
            }
 
          /* We have already displayed the form name.  */
-         printf (_("%c(index: 0x%s): %s"), delimiter,
-                 dwarf_vmatoa ("x", uvalue),
-                 dwarf_vmatoa ("x", idx));
+         if (idx != (dwarf_vma) -1)
+           printf (_("%c(index: 0x%s): %s"), delimiter,
+                   dwarf_vmatoa ("x", uvalue),
+                   dwarf_vmatoa ("x", idx));
        }
       break;