From: Alan Modra <amodra@gmail.com>
To: binutils@sourceware.org
Subject: PR29230, segv in lookup_symbol_in_variable_table
Date: Wed, 15 Jun 2022 13:36:22 +0930 [thread overview]
Message-ID: <YqlavuempyJ4uYjk@squeak.grove.modra.org> (raw)
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 --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:
--
Alan Modra
Australia Development Lab, IBM
reply other threads:[~2022-06-15 4:06 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YqlavuempyJ4uYjk@squeak.grove.modra.org \
--to=amodra@gmail.com \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).