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 14/17] libdwfl: Don't allocate phdrs and dyn on stack in dwfl_segment_report_module.


Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdwfl/ChangeLog                    |  6 ++++
 libdwfl/dwfl_segment_report_module.c | 67 ++++++++++++++++++++++--------------
 2 files changed, 47 insertions(+), 26 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 8753783..772de3e 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,11 @@
 2015-05-22  Mark Wielaard  <mjw@redhat.com>
 
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Allocate phdrs with malloc, not on stack. free in finish.
+	Allocate dyn with malloc, not on stack, free after use.
+
+2015-05-22  Mark Wielaard  <mjw@redhat.com>
+
 	* find-debuginfo.c (find_debuginfo_in_path): malloc or strdup,
 	instead of alloca or strdupa, local strings of unknown size.
 	Call free before return.
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 898457f..1c3b871 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -1,5 +1,5 @@
 /* Sniff out modules from ELF headers visible in memory segments.
-   Copyright (C) 2008-2012, 2014 Red Hat, Inc.
+   Copyright (C) 2008-2012, 2014, 2015 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -36,7 +36,6 @@
 #include <gelf.h>
 #include <inttypes.h>
 #include <sys/param.h>
-#include <alloca.h>
 #include <endian.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -278,8 +277,13 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   Elf *elf = NULL;
   int fd = -1;
 
+  /* We might have to reserve some memory for the phdrs.  Set to NULL
+     here so we can always safely free it.  */
+  void *phdrsp = NULL;
+
   inline int finish (void)
   {
+    free (phdrsp);
     release_buffer (&buffer, &buffer_available);
     if (elf != NULL)
       elf_end (elf);
@@ -400,14 +404,19 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   xlatefrom.d_buf = ph_buffer;
 
-  union
+  typedef union
   {
     Elf32_Phdr p32[phnum];
     Elf64_Phdr p64[phnum];
-  } phdrs;
+  } phdrsn;
 
-  xlateto.d_buf = &phdrs;
-  xlateto.d_size = sizeof phdrs;
+  phdrsp = malloc (sizeof (phdrsn));
+  if (phdrsp == NULL)
+    return finish ();
+  phdrsn *phdrs = (phdrsn *) phdrsp;
+
+  xlateto.d_buf = phdrs;
+  xlateto.d_size = sizeof (phdrsn);
 
   /* Track the bounds of the file visible in memory.  */
   GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
@@ -570,10 +579,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	found_bias = false;	/* Trigger error check.  */
       else
 	for (uint_fast16_t i = 0; i < phnum; ++i)
-	  consider_phdr (phdrs.p32[i].p_type,
-			 phdrs.p32[i].p_vaddr, phdrs.p32[i].p_memsz,
-			 phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz,
-			 phdrs.p32[i].p_align);
+	  consider_phdr (phdrs->p32[i].p_type,
+			 phdrs->p32[i].p_vaddr, phdrs->p32[i].p_memsz,
+			 phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz,
+			 phdrs->p32[i].p_align);
     }
   else
     {
@@ -581,10 +590,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	found_bias = false;	/* Trigger error check.  */
       else
 	for (uint_fast16_t i = 0; i < phnum; ++i)
-	  consider_phdr (phdrs.p64[i].p_type,
-			 phdrs.p64[i].p_vaddr, phdrs.p64[i].p_memsz,
-			 phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz,
-			 phdrs.p64[i].p_align);
+	  consider_phdr (phdrs->p64[i].p_type,
+			 phdrs->p64[i].p_vaddr, phdrs->p64[i].p_memsz,
+			 phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz,
+			 phdrs->p64[i].p_align);
     }
 
   finish_portion (&ph_buffer, &ph_buffer_size);
@@ -735,38 +744,44 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   const size_t dyn_entsize = (ei_class == ELFCLASS32
 			      ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
+  void *dyns = NULL;
   void *dyn_data = NULL;
   size_t dyn_data_size = 0;
   if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
       && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
     {
-      union
+      typedef union
       {
 	Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
 	Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
-      } dyn;
+      } dynn;
+      dyns = malloc (sizeof (dynn));
+      if (dyns == NULL)
+	return finish ();
+      dynn *dyn = (dynn *) dyns;
 
       xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
       xlatefrom.d_buf = (void *) dyn_data;
       xlatefrom.d_size = dyn_filesz;
-      xlateto.d_buf = &dyn;
-      xlateto.d_size = sizeof dyn;
+      xlateto.d_buf = dyn;
+      xlateto.d_size = sizeof (dynn);
 
       if (ei_class == ELFCLASS32)
 	{
 	  if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
-	    for (size_t i = 0; i < dyn_filesz / sizeof dyn.d32[0]; ++i)
-	      if (consider_dyn (dyn.d32[i].d_tag, dyn.d32[i].d_un.d_val))
+	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i)
+	      if (consider_dyn (dyn->d32[i].d_tag, dyn->d32[i].d_un.d_val))
 		break;
 	}
       else
 	{
 	  if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
-	    for (size_t i = 0; i < dyn_filesz / sizeof dyn.d64[0]; ++i)
-	      if (consider_dyn (dyn.d64[i].d_tag, dyn.d64[i].d_un.d_val))
+	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i)
+	      if (consider_dyn (dyn->d64[i].d_tag, dyn->d64[i].d_un.d_val))
 		break;
 	}
     }
+  free (dyns);
   finish_portion (&dyn_data, &dyn_data_size);
 
   /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
@@ -881,12 +896,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
 	  if (ei_class == ELFCLASS32)
 	    for (uint_fast16_t i = 0; i < phnum; ++i)
-	      read_phdr (phdrs.p32[i].p_type, phdrs.p32[i].p_vaddr,
-			 phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz);
+	      read_phdr (phdrs->p32[i].p_type, phdrs->p32[i].p_vaddr,
+			 phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz);
 	  else
 	    for (uint_fast16_t i = 0; i < phnum; ++i)
-	      read_phdr (phdrs.p64[i].p_type, phdrs.p64[i].p_vaddr,
-			 phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz);
+	      read_phdr (phdrs->p64[i].p_type, phdrs->p64[i].p_vaddr,
+			 phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz);
 	}
       else
 	{
-- 
1.8.3.1


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