public inbox for binutils-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] PR29230, segv in lookup_symbol_in_variable_table
@ 2022-06-15  4:06 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2022-06-15  4:06 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=31d6c13defeba7716ebc9d5c8f81f2f35fe39980

commit 31d6c13defeba7716ebc9d5c8f81f2f35fe39980
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Jun 14 12:46:42 2022 +0930

    PR29230, segv in lookup_symbol_in_variable_table
    
    The PR23230 testcase uses indexed strings without specifying
    SW_AT_str_offsets_base.  In this case we left u.str with garbage (from
    u.val) which then led to a segfault when attempting to access the
    string.  Fix that by clearing u.str.  The patch also adds missing
    sanity checks in the recently committed read_indexed_address and
    read_indexed_string functions.
    
            PR 29230
            * dwarf2.c (read_indexed_address): Return uint64_t.  Sanity check idx.
            (read_indexed_string): Use uint64_t for str_offset.  Sanity check idx.
            (read_attribute_value): Clear u.str for indexed string forms when
            DW_AT_str_offsets_base is not yet read or missing.

Diff:
---
 bfd/dwarf2.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 9 deletions(-)

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 51018e1ab45..aaa2d84887f 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -1353,13 +1353,13 @@ is_addrx_form (enum dwarf_form form)
 
 /* Returns the address in .debug_addr section using DW_AT_addr_base.
    Used to implement DW_FORM_addrx*.  */
-static bfd_vma
+static uint64_t
 read_indexed_address (uint64_t idx, struct comp_unit *unit)
 {
   struct dwarf2_debug *stash = unit->stash;
   struct dwarf2_debug_file *file = unit->file;
-  size_t addr_base = unit->dwarf_addr_offset;
   bfd_byte *info_ptr;
+  size_t offset;
 
   if (stash == NULL)
     return 0;
@@ -1369,12 +1369,23 @@ read_indexed_address (uint64_t idx, struct comp_unit *unit)
 		     &file->dwarf_addr_buffer, &file->dwarf_addr_size))
     return 0;
 
-  info_ptr = file->dwarf_addr_buffer + addr_base + idx * unit->offset_size;
+  if (_bfd_mul_overflow (idx, unit->offset_size, &offset))
+    return 0;
+
+  offset += unit->dwarf_addr_offset;
+  if (offset < unit->dwarf_addr_offset
+      || offset > file->dwarf_addr_size
+      || file->dwarf_addr_size - offset < unit->offset_size)
+    return 0;
+
+  info_ptr = file->dwarf_addr_buffer + offset;
 
   if (unit->offset_size == 4)
     return bfd_get_32 (unit->abfd, info_ptr);
-  else
+  else if (unit->offset_size == 8)
     return bfd_get_64 (unit->abfd, info_ptr);
+  else
+    return 0;
 }
 
 /* Returns the string using DW_AT_str_offsets_base.
@@ -1385,7 +1396,8 @@ read_indexed_string (uint64_t idx, struct comp_unit *unit)
   struct dwarf2_debug *stash = unit->stash;
   struct dwarf2_debug_file *file = unit->file;
   bfd_byte *info_ptr;
-  unsigned long str_offset;
+  uint64_t str_offset;
+  size_t offset;
 
   if (stash == NULL)
     return NULL;
@@ -1401,15 +1413,26 @@ read_indexed_string (uint64_t idx, struct comp_unit *unit)
 		     &file->dwarf_str_offsets_size))
     return NULL;
 
-  info_ptr = (file->dwarf_str_offsets_buffer
-	      + unit->dwarf_str_offset
-	      + idx * unit->offset_size);
+  if (_bfd_mul_overflow (idx, unit->offset_size, &offset))
+    return NULL;
+
+  offset += unit->dwarf_str_offset;
+  if (offset < unit->dwarf_str_offset
+      || offset > file->dwarf_str_offsets_size
+      || file->dwarf_str_offsets_size - offset < unit->offset_size)
+    return NULL;
+
+  info_ptr = file->dwarf_str_offsets_buffer + offset;
 
   if (unit->offset_size == 4)
     str_offset = bfd_get_32 (unit->abfd, info_ptr);
-  else
+  else if (unit->offset_size == 8)
     str_offset = bfd_get_64 (unit->abfd, info_ptr);
+  else
+    return NULL;
 
+  if (str_offset >= file->dwarf_str_size)
+    return NULL;
   return (const char *) file->dwarf_str_buffer + str_offset;
 }
 
@@ -1534,27 +1557,37 @@ read_attribute_value (struct attribute *  attr,
 	 is not yet read.  */
       if (unit->dwarf_str_offset != 0)
 	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+	attr->u.str = NULL;
       break;
     case DW_FORM_strx2:
       attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
       if (unit->dwarf_str_offset != 0)
 	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+	attr->u.str = NULL;
       break;
     case DW_FORM_strx3:
       attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
       if (unit->dwarf_str_offset != 0)
 	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+	attr->u.str = NULL;
       break;
     case DW_FORM_strx4:
       attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
       if (unit->dwarf_str_offset != 0)
 	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+	attr->u.str = NULL;
       break;
     case DW_FORM_strx:
       attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
 					   false, info_ptr_end);
       if (unit->dwarf_str_offset != 0)
 	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+	attr->u.str = NULL;
       break;
     case DW_FORM_exprloc:
     case DW_FORM_block:


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-15  4:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-15  4:06 [binutils-gdb] PR29230, segv in lookup_symbol_in_variable_table Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).