[PATCH] libdw: Don't overflow stack with user defined macro attributes array.

Mark Wielaard mjw at redhat.com
Tue Apr 21 13:54:51 UTC 2015


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 <mjw at redhat.com>
---
 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  <mjw at redhat.com>
+
+	* dwarf_getmacros.c (read_macros): Allocate attributes dynamically
+	when there are more than 8.
+
 2015-04-01  Petr Machata  <pmachata at redhat.com>
 
 	* 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



More information about the elfutils-devel mailing list