This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
[PATCH] libdw. Don't blow up stack in dwarf_getsrclines with lots of lines.
- From: Mark Wielaard <mjw at redhat dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Tue, 02 Jul 2013 16:46:58 +0200
- Subject: [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