Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- Perhaps this will help the getenv bug hunting (I assume we do the hunting on Linux platform only). So far it catches this and is stuck at getenv in git_pager(). diff --git a/exec_cmd.c b/exec_cmd.c index 125fa6f..d8be5ce 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -97,7 +97,7 @@ static void add_path(struct strbuf *out, const char *path) void setup_path(void) { - const char *old_path = getenv("PATH"); + char *old_path = xstrdup(getenv("PATH")); struct strbuf new_path = STRBUF_INIT; add_path(&new_path, git_exec_path()); @@ -110,6 +110,7 @@ void setup_path(void) setenv("PATH", new_path.buf, 1); + free(old_path); strbuf_release(&new_path); } contrib/getenv/Makefile | 2 ++ contrib/getenv/getenv.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 contrib/getenv/Makefile create mode 100644 contrib/getenv/getenv.c diff --git a/contrib/getenv/Makefile b/contrib/getenv/Makefile new file mode 100644 index 0000000..4881b85 --- /dev/null +++ b/contrib/getenv/Makefile @@ -0,0 +1,2 @@ +getenv.so: getenv.c + $(CC) -g -shared -fPIC -ldl -o $@ $< diff --git a/contrib/getenv/getenv.c b/contrib/getenv/getenv.c new file mode 100644 index 0000000..e351e10 --- /dev/null +++ b/contrib/getenv/getenv.c @@ -0,0 +1,67 @@ +#include <gnu/lib-names.h> +#include <sys/mman.h> +#include <dlfcn.h> +#include <execinfo.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +/* Global symbols for easy access from gdb */ +static char *getenv_current; +static char *getenv_prev; + +/* + * Intercept standard getenv() via LD_PRELOAD. The return value is + * made inaccessible by the next getenv() call. This helps catch + * places that ignore the statement "The string pointed to may be + * overwritten by a subsequent call to getenv()" [1]. + * + * The backtrace is appended after the env string, which may be + * helpful to identify where this getenv() is called in a core dump. + * + * [1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/getenv.html + */ +char *getenv(const char *name) +{ + static char *(*libc_getenv)(const char*); + char *value; + + if (!libc_getenv) { + void *libc = dlopen(LIBC_SO, RTLD_LAZY); + libc_getenv = dlsym(libc, "getenv"); + } + if (getenv_current) { + mprotect(getenv_current, strlen(getenv_current) + 1, PROT_NONE); + getenv_prev = getenv_current; + getenv_current = NULL; + } + + value = libc_getenv(name); + if (value) { + int len = strlen(value) + 1; + int backtrace_len = 0; + void *buffer[100]; + char **symbols; + int i, n; + + n = backtrace(buffer, 100); + symbols = backtrace_symbols(buffer, n); + if (symbols) { + for (i = 0;i < n; i++) + backtrace_len += strlen(symbols[i]) + 1; /* \n */ + backtrace_len++; /* NULL */ + } + + getenv_current = mmap(NULL, len + backtrace_len, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + memcpy(getenv_current, value, len); + value = getenv_current; + + if (symbols) { + char *p = getenv_current + len; + for (i = 0; i < n; i++) + p += sprintf(p, "%s\n", symbols[i]); + } + } + return value; +} -- 1.8.0.rc2.23.g1fb49df -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html