Hi, Benoit Lodej reported on the fortran list a bug in find_addr2line, namely that if the PATH string does not end in ":", the last PATH element is not tested. Rather than fixing the current implementation, I rewrote it in a simpler fashion by using the strtok_r function.
Tested that it fixes the original bug, and with strace & valgrind that everything seems Ok (no regtest since we don't have anything in the testsuite which tests the backtrace functionality, AFAIK). Ok for trunk/4.9/4.8? 2014-10-18 Janne Blomqvist <j...@gcc.gnu.org> PR libfortran/63589 * configure.ac: Check for strtok_r. * runtime/main.c (gfstrtok_r): Fallback implementation of strtok_r. (find_addr2line): Use strtok_r to split PATH. * config.h.in: Regenerated. * configure: Regenerated. -- Janne Blomqvist
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index 9d8e05c..b3150f4 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -275,6 +275,7 @@ if test "x${with_newlib}" = "xyes"; then AC_DEFINE(HAVE_GMTIME_R, 1, [Define if you have gmtime_r.]) AC_DEFINE(HAVE_STRNLEN, 1, [Define if you have strnlen.]) AC_DEFINE(HAVE_STRNDUP, 1, [Define if you have strndup.]) + AC_DEFINE(HAVE_STRTOK_R, 1, [Define if you have strtok_r.]) # At some point, we should differentiate between architectures # like x86, which have long double versions, and alpha/powerpc/etc., @@ -289,7 +290,7 @@ else strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \ getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \ readlink getgid getpid getppid getuid geteuid umask getegid \ - secure_getenv __secure_getenv mkostemp strnlen strndup) + secure_getenv __secure_getenv mkostemp strnlen strndup strtok_r) fi # Check strerror_r, cannot be above as versions with two and three arguments exist diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c index 8a572ec..448dfee 100644 --- a/libgfortran/runtime/main.c +++ b/libgfortran/runtime/main.c @@ -181,6 +181,16 @@ full_exe_path (void) } +#ifndef HAVE_STRTOK_R +static char* +gfstrtok_r (char *str, const char *delim, + char **saveptr __attribute__ ((unused))) +{ + return strtok (str, delim); +} +#define strtok_r gfstrtok_r +#endif + char *addr2line_path; /* Find addr2line and store the path. */ @@ -189,30 +199,32 @@ void find_addr2line (void) { #ifdef HAVE_ACCESS -#define A2L_LEN 10 +#define A2L_LEN 11 char *path = secure_getenv ("PATH"); if (!path) return; + char *tp = strdup (path); + if (!tp) + return; size_t n = strlen (path); - char ap[n + 1 + A2L_LEN]; - size_t ai = 0; - for (size_t i = 0; i < n; i++) + char *ap = xmalloc (n + A2L_LEN); + char *saveptr; + for (char *str = tp;; str = NULL) { - if (path[i] != ':') - ap[ai++] = path[i]; - else + char *token = strtok_r (str, ":", &saveptr); + if (!token) + break; + size_t toklen = strlen (token); + memcpy (ap, token, toklen); + memcpy (ap + toklen, "/addr2line", A2L_LEN); + if (access (ap, R_OK|X_OK) == 0) { - ap[ai++] = '/'; - memcpy (ap + ai, "addr2line", A2L_LEN); - if (access (ap, R_OK|X_OK) == 0) - { - addr2line_path = strdup (ap); - return; - } - else - ai = 0; + addr2line_path = strdup (ap); + break; } } + free (tp); + free (ap); #endif }