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 <[email protected]>
---
 libdw/ChangeLog         |  5 +++++
 libdw/dwarf_getmacros.c | 23 +++++++++++++++++++++--
 2 files changed, 26 insertions(+), 2 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  <[email protected]>
+
+       * dwarf_getmacros.c (read_macros): Allocate attributes dynamically
+       when there are more than 8.
+
 2015-04-01  Petr Machata  <[email protected]>
 
        * libdwP.h (DWARF_E_NOT_CUDIE): New enumerator.
diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c
index f9f2996..c5d47d6 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
@@ -385,7 +400,11 @@ read_macros (Dwarf *dbg, int sec_index,
        .attributes = attributes,
       };
 
-      if (callback (&macro, arg) != DWARF_CB_OK)
+      int res = callback (&macro, arg);
+      if (unlikely (attributesp != NULL))
+       free (attributesp);
+
+      if (res != DWARF_CB_OK)
        return readp - startp;
     }
 
-- 
2.1.0

Reply via email to