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. Don't blow up stack in dwarf_getsrclines with lots of lines.


When a CU has a really large number of lines dwarf_getsrclines could blow
up the stack because it uses alloca for temporary storage. Use malloc and
free if the number of lines gets too big.
---
 libdw/ChangeLog           |    6 ++++++
 libdw/dwarf_getsrclines.c |   22 ++++++++++++++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 59b6c63..c595891 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,9 @@
+2013-07-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Add new stack allocation
+	limit MAX_STACK_ALLOC.  After MAX_STACK_ALLOC lines use malloc in
+	NEW_LINE macro.  Free malloced line records if any at the end.
+
 2013-05-03  Mark Wielaard  <mjw@redhat.com>
 
 	* dwarf_getsrclines.c (dwarf_getsrclines): Only set end_sequence
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index fa4dd18..fb01465 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -328,12 +328,22 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
       struct linelist *linelist = NULL;
       unsigned int nlinelist = 0;
 
+      /* If there are a large number of lines don't blow up the stack.
+	 Keep track of the last malloced linelist record and free them
+	 through the next pointer at the end.  */
+#define MAX_STACK_ALLOC 4096
+      struct linelist *malloc_linelist = NULL;
+
       /* Adds a new line to the matrix.
 	 We cannot simply define a function because we want to use alloca.  */
 #define NEW_LINE(end_seq)						\
       do {								\
-	if (unlikely (add_new_line (alloca (sizeof (struct linelist)),	\
-				    end_seq)))				\
+	struct linelist *ll = (nlinelist < MAX_STACK_ALLOC		\
+			       ? alloca (sizeof (struct linelist))	\
+			       : malloc (sizeof (struct linelist)));	\
+	if (nlinelist >= MAX_STACK_ALLOC)				\
+	  malloc_linelist = ll;						\
+	if (unlikely (add_new_line (ll, end_seq)))			\
 	  goto invalid_data;						\
       } while (0)
 
@@ -712,6 +722,14 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
 	  cu->lines->info[i].files = files;
 	}
 
+      /* Free malloced line records, if any.  */
+      for (i = MAX_STACK_ALLOC; i < nlinelist; i++)
+	{
+	  struct linelist *ll = malloc_linelist->next;
+	  free (malloc_linelist);
+	  malloc_linelist = ll;
+	}
+
       /* Make sure the highest address for the CU is marked as end_sequence.
 	 This is required by the DWARF spec, but some compilers forget and
 	 dwfl_module_getsrc depends on it.  */
-- 
1.7.1


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