The sibling attribute should point after this DIE in the CU. Otherwise various algorithms might loop or go into infinite recursion walking the DIE tree.
Found by afl-fuzz. Signed-off-by: Mark Wielaard <[email protected]> --- libdw/ChangeLog | 5 +++++ libdw/dwarf_siblingof.c | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 2b47f4d..16ea9c3 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,10 @@ 2015-01-04 Mark Wielaard <[email protected]> + * dwarf_siblingof.c (dwarf_siblingof): Check sibling attribute + is after current DIE. + +2015-01-04 Mark Wielaard <[email protected]> + * cfi.c (enough_registers): Check reg < INT32_MAX / sizeof (dwarf_frame_register). diff --git a/libdw/dwarf_siblingof.c b/libdw/dwarf_siblingof.c index f8241b3..e598ae4 100644 --- a/libdw/dwarf_siblingof.c +++ b/libdw/dwarf_siblingof.c @@ -1,5 +1,5 @@ /* Return sibling of given DIE. - Copyright (C) 2003-2010, 2014 Red Hat, Inc. + Copyright (C) 2003-2010, 2014, 2015 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <[email protected]>, 2003. @@ -79,8 +79,11 @@ dwarf_siblingof (die, result) /* Something went wrong. */ return -1; + /* The sibling attribute should point after this DIE in the CU. + But not after the end of the CU. */ size_t size = sibattr.cu->endp - sibattr.cu->startp; - if (unlikely (offset >= size)) + size_t die_off = this_die.addr - this_die.cu->startp; + if (unlikely (offset >= size || offset <= die_off)) { __libdw_seterrno (DWARF_E_INVALID_DWARF); return -1; -- 1.8.3.1
