[Bug gdb/34358] New: [gdb] out-of-bounds read parsing a DW_OP_entry_value breg(0) nested block
firmiana402 at gmail dot com via Gdb-prs <[email protected]>
| Newsgroups | gmane.comp.gdb.bugs.discuss |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://sourceware.org/bugzilla/show_bug.cgi?id=34358
Bug ID: 34358
Summary: [gdb] out-of-bounds read parsing a DW_OP_entry_value
breg(0) nested block
Product: gdb
Version: HEAD
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: gdb
Assignee: unassigned at sourceware dot org
Reporter: firmiana402 at gmail dot com
Target Milestone: ---
dwarf_block_to_dwarf_reg_deref (gdb/dwarf2/expr.c) recognizes the restricted
nested blocks that DW_OP_entry_value accepts. Its documented contract is:
/* If BLOCK contains DW_FORM_block* with just DW_OP_breg*(0) and
DW_OP_deref*
return the DWARF register number. Otherwise return -1. ... */
After reading the breg register and its SLEB offset, it dispatches on the next
byte to find the required DW_OP_deref / DW_OP_deref_size, without first
checking
that a byte remains:
buf = gdb_read_sleb128 (buf, buf_end, &offset);
if (buf == NULL)
return -1;
if (offset != 0)
return -1;
if (*buf == DW_OP_deref)
{
buf++;
*deref_size_return = -1;
}
else if (*buf == DW_OP_deref_size)
{
buf++;
if (buf >= buf_end)
return -1;
*deref_size_return = *buf++;
}
else
return -1;
When the block ends right after the offset byte, gdb_read_sleb128 leaves
buf == buf_end. There is then no dereference opcode, which is precisely the
"Otherwise return -1" case; but instead of returning -1, the code evaluates
if (*buf == DW_OP_deref) and reads one byte past the end of the block.
The neighboring branches guard exactly this situation (buf >= buf_end after the
breg byte, and again after DW_OP_deref_size); the dispatch right after the SLEB
read is the one place that does not. Because the block is a view into the
surrounding DWARF expression buffer, a block positioned at the end of that
buffer makes this a read past the allocation, observable as a heap-buffer-
overflow read under AddressSanitizer.
A bounds check (buf >= buf_end) after the SLEB read addresses both aspects: it
avoids the out-of-bounds read, and it makes a block with no trailing
dereference
opcode return -1, as the contract already promises.
--
You are receiving this mail because:
You are on the CC list for the bug.