summaryrefslogtreecommitdiffstats
path: root/libdw/dwarf_getlocation.c
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2014-12-14 21:48:23 +0100
committerMark Wielaard <mjw@redhat.com>2014-12-17 16:35:56 +0100
commit7a053473c7bedd22e3db39c444a4cd8f97eace25 (patch)
treef98e9e7def17ec051170aaf663419628d84fae78 /libdw/dwarf_getlocation.c
parent9202665816763fad8524dd78a664dbcaa157b8d4 (diff)
libdw: Add get_uleb128 and get_sleb128 bounds checking.
Both get_uleb128 and get_sleb128 now take an end pointer to prevent reading too much data. Adjust all callers to provide the end pointer. There are still two exceptions. "Raw" dwarf_getabbrevattr and read_encoded_valued don't have a end pointer associated yet. They will have to be provided in the future. Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libdw/dwarf_getlocation.c')
-rw-r--r--libdw/dwarf_getlocation.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index 38e93e68..068f3853 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -104,7 +104,8 @@ store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
sizeof (struct loc_block_s), 1);
const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
- (void) __libdw_get_uleb128 (&data); // Ignored, equal to op->number.
+ // Ignored, equal to op->number. And data length already checked.
+ (void) __libdw_get_uleb128 (&data, data + len_leb128 (Dwarf_Word));
block->addr = op;
block->data = (unsigned char *) data;
block->length = op->number;
@@ -394,28 +395,28 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
case DW_OP_piece:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
- /* XXX Check size. */
- get_uleb128 (newloc->number, data);
+ get_uleb128 (newloc->number, data, end_data);
break;
case DW_OP_consts:
case DW_OP_breg0 ... DW_OP_breg31:
case DW_OP_fbreg:
- /* XXX Check size. */
- get_sleb128 (newloc->number, data);
+ get_sleb128 (newloc->number, data, end_data);
break;
case DW_OP_bregx:
- /* XXX Check size. */
- get_uleb128 (newloc->number, data);
- get_sleb128 (newloc->number2, data);
+ get_uleb128 (newloc->number, data, end_data);
+ if (unlikely (data >= end_data))
+ goto invalid;
+ get_sleb128 (newloc->number2, data, end_data);
break;
case DW_OP_bit_piece:
case DW_OP_GNU_regval_type:
- /* XXX Check size. */
- get_uleb128 (newloc->number, data);
- get_uleb128 (newloc->number2, data);
+ get_uleb128 (newloc->number, data, end_data);
+ if (unlikely (data >= end_data))
+ goto invalid;
+ get_uleb128 (newloc->number2, data, end_data);
break;
case DW_OP_implicit_value:
@@ -426,8 +427,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
/* start of block inc. len. */
newloc->number2 = (Dwarf_Word) (uintptr_t) data;
- /* XXX Check size. */
- get_uleb128 (newloc->number, data); /* Block length. */
+ get_uleb128 (newloc->number, data, end_data); /* Block length. */
if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
goto invalid;
data += newloc->number; /* Skip the block. */
@@ -438,23 +438,22 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
&newloc->number, IDX_debug_info, 0))
return -1;
- /* XXX Check size. */
- get_uleb128 (newloc->number2, data); /* Byte offset. */
+ if (unlikely (data >= end_data))
+ goto invalid;
+ get_uleb128 (newloc->number2, data, end_data); /* Byte offset. */
break;
case DW_OP_GNU_deref_type:
- if (unlikely (data >= end_data))
+ if (unlikely (data + 1 >= end_data))
goto invalid;
newloc->number = *data++;
- get_uleb128 (newloc->number2, data);
+ get_uleb128 (newloc->number2, data, end_data);
break;
case DW_OP_GNU_const_type:
{
size_t size;
-
- /* XXX Check size. */
- get_uleb128 (newloc->number, data);
+ get_uleb128 (newloc->number, data, end_data);
if (unlikely (data >= end_data))
goto invalid;