libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] [PATCH] Remedy stack overflow


From: Bob Bell
Subject: [Libunwind-devel] [PATCH] Remedy stack overflow
Date: Mon, 1 Dec 2008 15:43:49 -0500
User-agent: Mutt/1.5.11

The systems where I use libunwind have relatively small stacks.  Parts 
of libunwind put PATH_MAX on the stack, sometimes more than once.  This 
can lead to stack overflow, at which point my applications die without 
*ANY* indication of why they died.

I'm using the patch below.  It converts the big stack allocations I've 
found into mallocs.  It remedies the problems I've been seeing, at least 
for me.

 - Bob Bell

---
 src/os-linux.c                           |   21 ++++++++++++++++-----
 src/os-linux.h                           |   17 ++++++++++++++---
 src/ptrace/_UPT_find_proc_info.c         |    7 ++++++-
 src/ptrace/_UPT_get_dyn_info_list_addr.c |   13 ++++++++++---
 4 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/src/os-linux.c b/src/os-linux.c
index ae37d8f..a68300d 100644
--- a/src/os-linux.c
+++ b/src/os-linux.c
@@ -36,12 +36,19 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, 
unw_word_t ip,
                    unsigned long *segbase, unsigned long *mapoff)
 {
   struct map_iterator mi;
-  char path[PATH_MAX];
+  char *path;
   int found = 0;
   unsigned long hi;
+  int ret;
 
-  maps_init (&mi, pid);
-  while (maps_next (&mi, segbase, &hi, mapoff, path, sizeof (path)))
+  path = malloc (PATH_MAX);
+  if (!path)
+    return -1;
+  if (maps_init (&mi, pid) < 0) {
+    free (path);
+    return -1;
+  }
+  while (maps_next (&mi, segbase, &hi, mapoff, path, PATH_MAX))
     if (ip >= *segbase && ip < hi)
       {
        found = 1;
@@ -49,10 +56,14 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, 
unw_word_t ip,
       }
   maps_close (&mi);
 
-  if (!found)
+  if (!found) {
+    free (path);
     return -1;
+  }
 
-  return elf_map_image (ei, path);
+  ret = elf_map_image (ei, path);
+  free (path);
+  return ret;
 }
 
 #endif /* UNW_REMOTE_ONLY */
diff --git a/src/os-linux.h b/src/os-linux.h
index b2c9a8b..06c60a4 100644
--- a/src/os-linux.h
+++ b/src/os-linux.h
@@ -61,16 +61,21 @@ ltoa (char *buf, long val)
   return buf + len;
 }
 
-static inline void
+static inline int
 maps_init (struct map_iterator *mi, pid_t pid)
 {
-  char path[PATH_MAX], *cp;
+  char *path, *cp;
+
+  path = malloc (PATH_MAX);
+  if (!path)
+    return -1;
 
   memcpy (path, "/proc/", 6);
   cp = ltoa (path + 6, pid);
   memcpy (cp, "/maps", 6);
 
   mi->fd = open (path, O_RDONLY);
+  free (path);
   mi->offset = 0;
   mi->buf_size = 0;
 
@@ -88,6 +93,8 @@ maps_init (struct map_iterator *mi, pid_t pid)
        cp += mi->buf_size;
     }
   mi->buf = mi->buf_end = cp;
+
+  return 0;
 }
 
 static inline char *
@@ -199,7 +206,7 @@ maps_next (struct map_iterator *mi,
           unsigned long *low, unsigned long *high, unsigned long *offset,
           char *path, size_t path_size)
 {
-  char line[256 + PATH_MAX], perm[16], dash, colon, *cp;
+  char *line, perm[16], dash, colon, *cp;
   unsigned long major, minor, inum;
   size_t to_read = 256;        /* most lines fit in 256 characters easy */
   ssize_t i, nread;
@@ -207,6 +214,10 @@ maps_next (struct map_iterator *mi,
   if (mi->fd < 0)
     return 0;
 
+  line = malloc(256 + PATH_MAX);
+  if (!line)
+    return 0;
+
   while (1)
     {
       if (mi->buf)
diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c
index 67caaba..50c49b9 100644
--- a/src/ptrace/_UPT_find_proc_info.c
+++ b/src/ptrace/_UPT_find_proc_info.c
@@ -314,7 +314,7 @@ static unw_dyn_info_t *
 get_unwind_info (struct UPT_info *ui, unw_addr_space_t as, unw_word_t ip)
 {
   unsigned long segbase, mapoff;
-  char path[PATH_MAX];
+  char *path = NULL;
   unw_dyn_info_t *di;
 
 #if UNW_TARGET_IA64 && defined(__linux)
@@ -341,9 +341,14 @@ get_unwind_info (struct UPT_info *ui, unw_addr_space_t as, 
unw_word_t ip)
   if (tdep_get_elf_image (&ui->ei, ui->pid, ip, &segbase, &mapoff) < 0)
     return NULL;
 
+  path = malloc (PATH_MAX);
+  if (!path)
+    return NULL;
+
   /* Here, SEGBASE is the starting-address of the (mmap'ped) segment
      which covers the IP we're looking for.  */
   di = _UPTi_find_unwind_table (ui, as, path, segbase, mapoff);
+  free (path);
   if (!di
       /* This can happen in corner cases where dynamically generated
          code falls into the same page that contains the data-segment
diff --git a/src/ptrace/_UPT_get_dyn_info_list_addr.c 
b/src/ptrace/_UPT_get_dyn_info_list_addr.c
index e0ea2f4..675b10c 100644
--- a/src/ptrace/_UPT_get_dyn_info_list_addr.c
+++ b/src/ptrace/_UPT_get_dyn_info_list_addr.c
@@ -36,13 +36,19 @@ get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, 
void *arg,
   unsigned long lo, hi, off;
   struct UPT_info *ui = arg;
   struct map_iterator mi;
-  char path[PATH_MAX];
+  char *path;
   unw_dyn_info_t *di;
   unw_word_t res;
   int count = 0;
 
-  maps_init (&mi, ui->pid);
-  while (maps_next (&mi, &lo, &hi, &off, path, sizeof (path)))
+  path = malloc(PATH_MAX);
+  if (!path)
+    return -1;
+  if (maps_init (&mi, ui->pid) < 0) {
+    free(path);
+    return -1;
+  }
+  while (maps_next (&mi, &lo, &hi, &off, path, PATH_MAX))
     {
       if (off)
        continue;
@@ -74,6 +80,7 @@ get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, 
void *arg,
        }
     }
   maps_close (&mi);
+  free(path);
   *countp = count;
   return 0;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]