[Commits] b032472: Fixed a crash during stacktrace printing if addr2line failed to start.

Vicentiu Ciorbaru vicentiu at mariadb.org
Mon Dec 14 22:38:07 EET 2015


revision-id: b0324720fb0de5aaf34db9955047c5fae17b8e2b (mariadb-10.1.9-13-gb032472)
parent(s): 44b107da90a106c128dca278d04c68d804e51497
committer: Vicențiu Ciorbaru
timestamp: 2015-12-14 22:38:07 +0200
message:

Fixed a crash during stacktrace printing if addr2line failed to start.

In order to get all the input from addr2line we must read in a loop,
until the response is complete. Also, in case that the response is
malformed, we must not end up reading invalid memory.

---
 mysys/my_addr_resolve.c | 66 ++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 14 deletions(-)

diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c
index 9c9a7d9..f9f40bc 100644
--- a/mysys/my_addr_resolve.c
+++ b/mysys/my_addr_resolve.c
@@ -145,30 +145,68 @@ static int initialized= 0;
 static char output[1024];
 int my_addr_resolve(void *ptr, my_addr_loc *loc)
 {
-  char input[32], *s;
+  char input[32];
   size_t len;
 
   len= my_snprintf(input, sizeof(input), "%p\n", ptr - offset);
   if (write(in[1], input, len) <= 0)
     return 1;
-  if (read(out[0], output, sizeof(output)) <= 0)
+
+  ssize_t total_bytes_read = 0;
+  ssize_t extra_bytes_read = 0;
+
+  fd_set set;
+  struct timeval timeout;
+  FD_ZERO(&set);
+  FD_SET(out[0], &set);
+
+  /* 10 ms should be plenty of time for addr2line to issue a response. */
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 10000;
+  /* Read in a loop till all the output from addr2line is complete. */
+  while (select(out[0] + 1, &set, NULL, NULL, &timeout) > 0)
+  {
+    extra_bytes_read= read(out[0], output + total_bytes_read,
+                           sizeof(output) - total_bytes_read);
+    if (extra_bytes_read < 0)
+      return 1;
+    total_bytes_read += extra_bytes_read;
+  }
+
+  /* Failed starting addr2line. */
+  if (total_bytes_read == 0)
     return 1;
-  loc->func= s= output;
-  while (*s != '\n')
-    s++;
-  *s++= 0;
-  loc->file= s;
-  while (*s != ':')
-    s++;
-  *s++= 0;
 
+  int filename_start = -1;
+  int line_number_start = -1;
+  /* Go through the addr2line response and get the required data.
+     The response is structured in 2 lnes. The first line contains the function
+     name, while the second one contains <filename>:<line number> */
+  for (ssize_t i = 0; i < total_bytes_read; i++) {
+    if (output[i] == '\n') {
+      filename_start = i + 1;
+      output[i] = '\0';
+    }
+    if (filename_start != -1 && output[i] == ':') {
+      line_number_start = i + 1;
+      output[i] = '\0';
+    }
+    if (line_number_start != -1) {
+      loc->line= atoi(output + line_number_start);
+      break;
+    }
+  }
+  /* Response is malformed. */
+  if (filename_start == -1 || line_number_start == -1)
+   return 1;
+
+  loc->func= output;
+  loc->file= output + filename_start;
+
+  /* Addr2line was unable to extract any meaningful information. */
   if (strcmp(loc->file, "??") == 0)
     return 1;
 
-  loc->line= 0;
-  while (isdigit(*s))
-    loc->line = loc->line * 10 + (*s++ - '0');
-  *s = 0;
   loc->file= strip_path(loc->file);
 
   return 0;


More information about the commits mailing list