diff options
Diffstat (limited to 'libdw/dwarf_getabbrev.c')
| -rw-r--r-- | libdw/dwarf_getabbrev.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c index 87d89c1b..0efde45b 100644 --- a/libdw/dwarf_getabbrev.c +++ b/libdw/dwarf_getabbrev.c @@ -1,5 +1,5 @@ /* Get abbreviation at given offset. - Copyright (C) 2003, 2004, 2005, 2006 Red Hat, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2014 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <[email protected]>, 2003. @@ -31,7 +31,6 @@ # include <config.h> #endif -#include <assert.h> #include <dwarf.h> #include "libdwP.h" @@ -78,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; @@ -97,7 +98,14 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result) { foundit = true; - assert (abb->offset == offset); + if (unlikely (abb->offset != offset)) + { + /* A duplicate abbrev code at a different offset, + that should never happen. */ + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } /* If the caller doesn't need the length we are done. */ if (lengthp == NULL) @@ -108,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; @@ -119,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); |
