diff --git a/src/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c index ec314c03f5..d98993be45 100644 --- a/src/backend/utils/misc/ps_status.c +++ b/src/backend/utils/misc/ps_status.c @@ -122,7 +122,8 @@ static char **save_argv; * (The original argv[] will not be overwritten by this routine, but may be * overwritten during init_ps_display. Also, the physical location of the * environment strings may be moved, so this should be called before any code - * that might try to hang onto a getenv() result.) + * that might try to hang onto a getenv() result. But see hack for musl + * within.) * * Note that in case of failure this cannot call elog() as that is not * initialized yet. We rely on write_stderr() instead. @@ -137,7 +138,7 @@ save_ps_display_args(int argc, char **argv) /* * If we're going to overwrite the argv area, count the available space. - * Also move the environment to make additional room. + * Also move the environment strings to make additional room. */ { char *end_of_area = NULL; @@ -166,7 +167,33 @@ save_ps_display_args(int argc, char **argv) for (i = 0; environ[i] != NULL; i++) { if (end_of_area + 1 == environ[i]) - end_of_area = environ[i] + strlen(environ[i]); + { + /* + * The musl dynamic linker keeps a static pointer to the + * initial value of LD_LIBRARY_PATH, if that is defined in the + * process's environment. Therefore, we must not overwrite the + * value of that setting and thus cannot advance end_of_area + * beyond it. Musl does not define any identifying compiler + * symbol, so we have to do this unless we see a symbol + * identifying a Linux libc we know is safe. + */ +#if defined(__linux__) && (!defined(__GLIBC__) && !defined(__UCLIBC__)) + if (strncmp(environ[i], "LD_LIBRARY_PATH=", 16) == 0) + { + /* + * We can overwrite the name, but stop at the equals sign. + * Future loop iterations will not find any more + * contiguous space, but we don't break early because we + * need to count the total number of environ[] entries. + */ + end_of_area = environ[i] + 15; + } + else +#endif + { + end_of_area = environ[i] + strlen(environ[i]); + } + } } ps_buffer = argv[0]; @@ -201,7 +228,7 @@ save_ps_display_args(int argc, char **argv) * If we're going to change the original argv[] then make a copy for * argument parsing purposes. * - * (NB: do NOT think to remove the copying of argv[], even though + * NB: do NOT think to remove the copying of argv[], even though * postmaster.c finishes looking at argv[] long before we ever consider * changing the ps display. On some platforms, getopt() keeps pointers * into the argv array, and will get horribly confused when it is