>From c91d13dd269b08432e8c1cd4385952071097d827 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 21 Apr 2015 15:46:01 +0200 Subject: [PATCH] libdw: Don't overflow stack with user defined macro attributes array. In theory user defined debug macros can have an arbitrary number of arguments. Don't allocate them all on stack. If there are more than 8 (arbitrary number, but no sane macro should have more arguments), then dynamically allocate and free the attributes. Found by gcc -fsanitize=undefined. Which pointed out the nforms could be zero, creating an empty vla (which could cause undefined behavior). Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 5 +++++ libdw/dwarf_getmacros.c | 30 ++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 3abb382..87c7d82 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,8 @@ +2015-04-21 Mark Wielaard + + * dwarf_getmacros.c (read_macros): Allocate attributes dynamically + when there are more than 8. + 2015-04-01 Petr Machata * libdwP.h (DWARF_E_NOT_CUDIE): New enumerator. diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c index f9f2996..740368e 100644 --- a/libdw/dwarf_getmacros.c +++ b/libdw/dwarf_getmacros.c @@ -361,7 +361,22 @@ read_macros (Dwarf *dbg, int sec_index, .endp = (void *) endp, }; - Dwarf_Attribute attributes[proto->nforms]; + Dwarf_Attribute *attributes; + Dwarf_Attribute *attributesp = NULL; + Dwarf_Attribute nattributes[8]; + if (unlikely (proto->nforms > 8)) + { + attributesp = malloc (sizeof (Dwarf_Attribute) * proto->nforms); + if (attributesp == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + attributes = attributesp; + } + else + attributes = &nattributes[0]; + for (Dwarf_Word i = 0; i < proto->nforms; ++i) { /* We pretend this is a DW_AT_GNU_macros attribute so that @@ -373,8 +388,11 @@ read_macros (Dwarf *dbg, int sec_index, attributes[i].cu = &fake_cu; size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp); - if (len == (size_t) -1) - return -1; + if (unlikely (len == (size_t) -1)) + { + free (attributesp); + return -1; + } readp += len; } @@ -385,7 +403,11 @@ read_macros (Dwarf *dbg, int sec_index, .attributes = attributes, }; - if (callback (¯o, arg) != DWARF_CB_OK) + int res = callback (¯o, arg); + if (unlikely (attributesp != NULL)) + free (attributesp); + + if (res != DWARF_CB_OK) return readp - startp; } -- 2.1.0