From 59480ba86fdaad7eb2e104b69af4a3b07e20d6fb Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 23 Nov 2014 23:21:05 +0100 Subject: libdw: Always check __libdw_find_attr return value. __libdw_find_attr will return NULL and might not set code or form. Only use code or form if the returned address is not NULL. Signed-off-by: Mark Wielaard --- libdw/dwarf_hasattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libdw/dwarf_hasattr.c') diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c index 7933c1c3..fb7e1d5e 100644 --- a/libdw/dwarf_hasattr.c +++ b/libdw/dwarf_hasattr.c @@ -1,5 +1,5 @@ /* Check whether given DIE has specific attribute. - Copyright (C) 2003, 2005 Red Hat, Inc. + Copyright (C) 2003, 2005, 2014 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper , 2003. @@ -45,8 +45,8 @@ dwarf_hasattr (die, search_name) /* Search for the attribute with the given name. */ unsigned int code; - (void) __libdw_find_attr (die, search_name, &code, NULL); + unsigned char *addr = __libdw_find_attr (die, search_name, &code, NULL); - return code == search_name; + return addr != NULL && code == search_name; } INTDEF (dwarf_hasattr) -- cgit v1.2.3 From 64e44dfc9420940d238e5fdad4fadce3c1f5f05e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 10 Dec 2014 18:33:34 -0800 Subject: libdw: optimize dwarf_hasattr to just look at abbrev To just check the presence of an attribute, we only need to look at the abbreviation data. This optimization avoids reading over die data at all, except possibly just to get the abbrev code. Signed-off-by: Josh Stone --- libdw/dwarf_hasattr.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'libdw/dwarf_hasattr.c') diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c index fb7e1d5e..6ed1a98c 100644 --- a/libdw/dwarf_hasattr.c +++ b/libdw/dwarf_hasattr.c @@ -43,10 +43,44 @@ dwarf_hasattr (die, search_name) if (die == NULL) return 0; - /* Search for the attribute with the given name. */ - unsigned int code; - unsigned char *addr = __libdw_find_attr (die, search_name, &code, NULL); + /* Find the abbreviation entry. */ + Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL); + if (unlikely (abbrevp == DWARF_END_ABBREV)) + { + invalid_dwarf: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return 0; + } - return addr != NULL && code == search_name; + Dwarf *dbg = die->cu->dbg; + + /* Search the name attribute. */ + unsigned char *const endp + = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + + dbg->sectiondata[IDX_debug_abbrev]->d_size); + + const unsigned char *attrp = abbrevp->attrp; + while (1) + { + /* Are we still in bounds? This test needs to be refined. */ + if (unlikely (attrp + 1 >= endp)) + goto invalid_dwarf; + + /* Get attribute name and form. + + XXX We don't check whether this reads beyond the end of the + section. */ + unsigned int attr_name; + get_uleb128 (attr_name, attrp); + unsigned int attr_form; + get_uleb128 (attr_form, attrp); + + /* We can stop if we found the attribute with value zero. */ + if (attr_name == 0 || attr_form == 0) + return 0; + + if (attr_name == search_name) + return 1; + } } INTDEF (dwarf_hasattr) -- cgit v1.2.3 From 7a053473c7bedd22e3db39c444a4cd8f97eace25 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 14 Dec 2014 21:48:23 +0100 Subject: 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 --- libdw/dwarf_hasattr.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'libdw/dwarf_hasattr.c') diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c index 6ed1a98c..812c09bc 100644 --- a/libdw/dwarf_hasattr.c +++ b/libdw/dwarf_hasattr.c @@ -63,17 +63,16 @@ dwarf_hasattr (die, search_name) while (1) { /* Are we still in bounds? This test needs to be refined. */ - if (unlikely (attrp + 1 >= endp)) + if (unlikely (attrp >= endp)) goto invalid_dwarf; - /* Get attribute name and form. - - XXX We don't check whether this reads beyond the end of the - section. */ + /* Get attribute name and form. */ unsigned int attr_name; - get_uleb128 (attr_name, attrp); + get_uleb128 (attr_name, attrp, endp); unsigned int attr_form; - get_uleb128 (attr_form, attrp); + if (unlikely (attrp >= endp)) + goto invalid_dwarf; + get_uleb128 (attr_form, attrp, endp); /* We can stop if we found the attribute with value zero. */ if (attr_name == 0 || attr_form == 0) -- cgit v1.2.3