summaryrefslogtreecommitdiffstats
path: root/libdw/dwarf_getabbrev.c
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2014-12-14 21:48:23 +0100
committerMark Wielaard <[email protected]>2014-12-17 16:35:56 +0100
commit7a053473c7bedd22e3db39c444a4cd8f97eace25 (patch)
treef98e9e7def17ec051170aaf663419628d84fae78 /libdw/dwarf_getabbrev.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 <[email protected]>
Diffstat (limited to 'libdw/dwarf_getabbrev.c')
-rw-r--r--libdw/dwarf_getabbrev.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c
index 6bb2bd76..0efde45b 100644
--- a/libdw/dwarf_getabbrev.c
+++ b/libdw/dwarf_getabbrev.c
@@ -77,9 +77,11 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
consists of two parts. The first part is an unsigned LEB128
number representing the attribute's name. The second part is
an unsigned LEB128 number representing the attribute's form. */
+ const unsigned char *end = (dbg->sectiondata[IDX_debug_abbrev]->d_buf
+ + dbg->sectiondata[IDX_debug_abbrev]->d_size);
const unsigned char *start_abbrevp = abbrevp;
unsigned int code;
- get_uleb128 (code, abbrevp);
+ get_uleb128 (code, abbrevp, end);
/* Check whether this code is already in the hash table. */
bool foundit = false;
@@ -100,6 +102,7 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
{
/* A duplicate abbrev code at a different offset,
that should never happen. */
+ invalid:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
@@ -113,7 +116,11 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
overwrite its content. This must not be a problem, since the
content better be the same. */
abb->code = code;
- get_uleb128 (abb->tag, abbrevp);
+ if (abbrevp >= end)
+ goto invalid;
+ get_uleb128 (abb->tag, abbrevp, end);
+ if (abbrevp + 1 >= end)
+ goto invalid;
abb->has_children = *abbrevp++ == DW_CHILDREN_yes;
abb->attrp = (unsigned char *) abbrevp;
abb->offset = offset;
@@ -124,8 +131,12 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
unsigned int attrform;
do
{
- get_uleb128 (attrname, abbrevp);
- get_uleb128 (attrform, abbrevp);
+ if (abbrevp >= end)
+ goto invalid;
+ get_uleb128 (attrname, abbrevp, end);
+ if (abbrevp >= end)
+ goto invalid;
+ get_uleb128 (attrform, abbrevp, end);
}
while (attrname != 0 && attrform != 0 && ++abb->attrcnt);