Signed-off-by: Mark Wielaard <[email protected]>
---
 libdwfl/ChangeLog        |  6 ++++++
 libdwfl/find-debuginfo.c | 36 ++++++++++++++++++++++++++++++------
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index f08200e..8753783 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,11 @@
 2015-05-22  Mark Wielaard  <[email protected]>
 
+       * find-debuginfo.c (find_debuginfo_in_path): malloc or strdup,
+       instead of alloca or strdupa, local strings of unknown size.
+       Call free before return.
+
+2015-05-22  Mark Wielaard  <[email protected]>
+
        * dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Return
        error when id_len too small or too large. strdup, not strdupa,
        and free path when done.
diff --git a/libdwfl/find-debuginfo.c b/libdwfl/find-debuginfo.c
index 3f5314a..7e0f655 100644
--- a/libdwfl/find-debuginfo.c
+++ b/libdwfl/find-debuginfo.c
@@ -161,6 +161,7 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char 
*file_name,
   bool cancheck = debuglink_crc != (GElf_Word) 0;
 
   const char *file_basename = file_name == NULL ? NULL : basename (file_name);
+  char *localname = NULL;
   if (debuglink_file == NULL)
     {
       /* For a alt debug multi file we need a name, for a separate debug
@@ -172,7 +173,9 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char 
*file_name,
        }
 
       size_t len = strlen (file_basename);
-      char *localname = alloca (len + sizeof ".debug");
+      localname = malloc (len + sizeof ".debug");
+      if (localname == NULL)
+       return -1;
       memcpy (localname, file_basename, len);
       memcpy (&localname[len], ".debug", sizeof ".debug");
       debuglink_file = localname;
@@ -183,11 +186,17 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char 
*file_name,
      indicated by the debug directory path setting.  */
 
   const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
-  char *path = strdupa ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
-                       ?: DEFAULT_DEBUGINFO_PATH);
+  char *localpath = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
+                           ?: DEFAULT_DEBUGINFO_PATH);
+  if (localpath == NULL)
+    {
+      free (localname);
+      return -1;
+    }
 
   /* A leading - or + in the whole path sets whether to check file CRCs.  */
   bool defcheck = true;
+  char *path = localpath;
   if (path[0] == '-' || path[0] == '+')
     {
       defcheck = path[0] == '+';
@@ -205,7 +214,13 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char 
*file_name,
     }
 
   char *file_dirname = (file_basename == file_name ? NULL
-                       : strndupa (file_name, file_basename - 1 - file_name));
+                       : strndup (file_name, file_basename - 1 - file_name));
+  if (file_basename != file_name && file_dirname == NULL)
+    {
+      free (localpath);
+      free (localname);
+      return -1;
+    }
   char *p;
   while ((p = strsep (&path, ":")) != NULL)
     {
@@ -270,7 +285,7 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char 
*file_name,
                if (fd < 0)
                  {
                    if (errno != ENOENT && errno != ENOTDIR)
-                     return -1;
+                     goto fail_free;
                    else
                      continue;
                  }
@@ -278,8 +293,17 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char 
*file_name,
              }
            continue;
          default:
-           return -1;
+           {
+           fail_free:
+             free (localpath);
+             free (localname);
+             free (file_dirname);
+             return -1;
+           }
          }
+      free (localpath);
+      free (localname);
+      free (file_dirname);
       if (validate (mod, fd, check, debuglink_crc))
        {
          *debuginfo_file_name = fname;
-- 
1.8.3.1

Reply via email to