[PATCH] libdw: Check DW_AT_sibling attribute offset is after current DIE.

Mark Wielaard mjw at redhat.com
Sun Jan 4 23:09:26 UTC 2015


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 <mjw at redhat.com>
---
 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  <mjw at redhat.com>
 
+	* dwarf_siblingof.c (dwarf_siblingof): Check sibling attribute
+	is after current DIE.
+
+2015-01-04  Mark Wielaard  <mjw at redhat.com>
+
 	* 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 <drepper at redhat.com>, 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



More information about the elfutils-devel mailing list