This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] libdw: Break dwarf_aggregate_size recursion because of type cycles.


Found by afl-fuzz. An array type (indirectly) referring to itself in the
DIE tree could blow up the stack when dwarf_aggregate_size was called.
Limit the recursion depth to MAX_DEPTH (256) entries.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdw/ChangeLog              |  8 ++++++++
 libdw/dwarf_aggregate_size.c | 28 +++++++++++++++++++---------
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 754a7e15..131084c6 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,11 @@
+2018-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_aggregate_size.c (array_size): New depth argument. Use
+	aggregate_size instead of dwarf_aggregate_size and pass depth.
+	(aggregate_size): New depth argument. Check depth isn't bigger
+	than MAX_DEPTH (256). Pass depth to recursive calls.
+	(dwarf_aggregate_size): ass zero as depth to aggregate_size.
+
 2018-06-18  Mark Wielaard  <mark@klomp.org>
 
 	* dwarf_peel_type.c (dwarf_peel_type): Limit modifier chain to 64.
diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c
index d20db71a..75105e4d 100644
--- a/libdw/dwarf_aggregate_size.c
+++ b/libdw/dwarf_aggregate_size.c
@@ -46,13 +46,17 @@ get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
   return type;
 }
 
+static int aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
+			   Dwarf_Die *type_mem, int depth);
+
 static int
 array_size (Dwarf_Die *die, Dwarf_Word *size,
-	    Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
+	    Dwarf_Attribute *attr_mem, int depth)
 {
   Dwarf_Word eltsize;
-  if (INTUSE(dwarf_aggregate_size) (get_type (die, attr_mem, type_mem),
-				    &eltsize) != 0)
+  Dwarf_Die type_mem, aggregate_type_mem;
+  if (aggregate_size (get_type (die, attr_mem, &type_mem), &eltsize,
+		      &aggregate_type_mem, depth) != 0)
       return -1;
 
   /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type
@@ -167,11 +171,14 @@ array_size (Dwarf_Die *die, Dwarf_Word *size,
 }
 
 static int
-aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem)
+aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
+		Dwarf_Die *type_mem, int depth)
 {
   Dwarf_Attribute attr_mem;
 
-  if (die == NULL)
+/* Arrays of arrays of subrange types of arrays... Don't recurse too deep.  */
+#define MAX_DEPTH 256
+  if (die == NULL || depth++ >= MAX_DEPTH)
     return -1;
 
   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
@@ -180,11 +187,14 @@ aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem)
   switch (INTUSE(dwarf_tag) (die))
     {
     case DW_TAG_subrange_type:
-      return aggregate_size (get_type (die, &attr_mem, type_mem),
-			     size, type_mem); /* Tail call.  */
+      {
+	Dwarf_Die aggregate_type_mem;
+	return aggregate_size (get_type (die, &attr_mem, type_mem),
+			       size, &aggregate_type_mem, depth);
+      }
 
     case DW_TAG_array_type:
-      return array_size (die, size, &attr_mem, type_mem);
+      return array_size (die, size, &attr_mem, depth);
 
     /* Assume references and pointers have pointer size if not given an
        explicit DW_AT_byte_size.  */
@@ -207,7 +217,7 @@ dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
   if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
     return -1;
 
-  return aggregate_size (&die_mem, size, &type_mem);
+  return aggregate_size (&die_mem, size, &type_mem, 0);
 }
 INTDEF (dwarf_aggregate_size)
 OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
-- 
2.17.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]