summaryrefslogtreecommitdiffstats
path: root/libdw
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-06-18 00:58:24 +0200
committerMark Wielaard <mark@klomp.org>2018-06-20 13:52:01 +0200
commita8efc328a5a88921e030638c257d36979f19db9f (patch)
tree0bd0bd5a03837a0f68f084d632b9f1eefd89e34c /libdw
parent822a06cd87496278298ab3167d6bb5968762ec20 (diff)
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>
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog8
-rw-r--r--libdw/dwarf_aggregate_size.c28
2 files changed, 27 insertions, 9 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 2f7ac2cd..4280c553 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,5 +1,13 @@
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.
2018-06-18 Mark Wielaard <mark@klomp.org>
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)