Hello,

The attached patch to libbacktrace is intended to fix a memory
allocation bug involving reading of line table information.

The scenario of interest takes place when libbacktrace reads a DWARF
line table whose directory count is zero (an unusual case). If the
memory allocator invocation triggers a call to mmap, this can cause
the size passed to mmap to be zero, resulting in an EINVAL error.  The
fix is to detect the zero-directory case and avoid invoking the
allocation helper with a zero size.

Questions + comments welcome.

Thanks, Than

---

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 80c64034092..bcb2c0991ef 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -1563,16 +1563,15 @@ add_line (struct backtrace_state *state,
struct dwarf_data *ddata,
   return 1;
 }

-/* Free the line header information.  If FREE_FILENAMES is true we
-   free the file names themselves, otherwise we leave them, as there
-   may be line structures pointing to them.  */
+/* Free the line header information.  */

 static void
 free_line_header (struct backtrace_state *state, struct line_header *hdr,
   backtrace_error_callback error_callback, void *data)
 {
-  backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),
-  error_callback, data);
+  if (hdr->dirs_count != 0)
+    backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),
+                    error_callback, data);
   backtrace_free (state, hdr->filenames,
   hdr->filenames_count * sizeof (char *),
   error_callback, data);
@@ -1633,12 +1632,16 @@ read_line_header (struct backtrace_state
*state, struct unit *u,
       ++hdr->dirs_count;
     }

-  hdr->dirs = ((const char **)
-       backtrace_alloc (state,
- hdr->dirs_count * sizeof (const char *),
- line_buf->error_callback, line_buf->data));
-  if (hdr->dirs == NULL)
-    return 0;
+  hdr->dirs = NULL;
+  if (hdr->dirs_count != 0)
+    {
+      hdr->dirs = ((const char **)
+                   backtrace_alloc (state,
+                                    hdr->dirs_count * sizeof (const char *),
+                                    line_buf->error_callback, line_buf->data));
+      if (hdr->dirs == NULL)
+        return 0;
+    }

   i = 0;
   while (*hdr_buf.buf != '\0')

Reply via email to