diff options
author | Mark Wielaard <[email protected]> | 2014-12-14 21:48:23 +0100 |
---|---|---|
committer | Mark Wielaard <[email protected]> | 2014-12-17 16:35:56 +0100 |
commit | 7a053473c7bedd22e3db39c444a4cd8f97eace25 (patch) | |
tree | f98e9e7def17ec051170aaf663419628d84fae78 /libdw/dwarf_getabbrev.c | |
parent | 9202665816763fad8524dd78a664dbcaa157b8d4 (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.c | 19 |
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); |