diff options
-rw-r--r-- | ChangeLog.txt | 3 | ||||
-rw-r--r-- | ports/common/guts/execv.c | 2 | ||||
-rw-r--r-- | ports/common/guts/execve.c | 2 | ||||
-rw-r--r-- | ports/common/guts/execvp.c | 2 | ||||
-rw-r--r-- | ports/common/guts/fork.c | 2 | ||||
-rw-r--r-- | ports/linux/newclone/pseudo_wrappers.c | 2 | ||||
-rw-r--r-- | ports/linux/oldclone/pseudo_wrappers.c | 2 | ||||
-rw-r--r-- | ports/unix/guts/popen.c | 2 | ||||
-rw-r--r-- | ports/unix/guts/system.c | 2 | ||||
-rw-r--r-- | pseudo.h | 1 | ||||
-rw-r--r-- | pseudo_util.c | 27 |
11 files changed, 39 insertions, 8 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 844e177..347a591 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -8,6 +8,9 @@ * (seebs) send a round-trip message to the server before exiting if any messages have been sent, so the program won't exit before the server processed those messages. + * (pabigot) Don't memory-leak on checks for PSEUDO_UNLOAD, also + check the correct environment when spawning new things. (Contributed + by Peter A. Bigot). 2014-05-15: * (seebs) drop flags when calling fchmodat() to appease GNU tar. diff --git a/ports/common/guts/execv.c b/ports/common/guts/execv.c index 763e1f9..3e1f820 100644 --- a/ports/common/guts/execv.c +++ b/ports/common/guts/execv.c @@ -19,7 +19,7 @@ } pseudo_setupenv(); - if (pseudo_get_value("PSEUDO_UNLOAD")) + if (pseudo_has_unload(NULL)) pseudo_dropenv(); /* if exec() fails, we may end up taking signals unexpectedly... diff --git a/ports/common/guts/execve.c b/ports/common/guts/execve.c index a003657..ff6a44e 100644 --- a/ports/common/guts/execve.c +++ b/ports/common/guts/execve.c @@ -20,7 +20,7 @@ } new_environ = pseudo_setupenvp(envp); - if (pseudo_get_value("PSEUDO_UNLOAD")) + if (pseudo_has_unload(new_environ)) new_environ = pseudo_dropenvp(new_environ); /* if exec() fails, we may end up taking signals unexpectedly... diff --git a/ports/common/guts/execvp.c b/ports/common/guts/execvp.c index 5e75be7..04253c3 100644 --- a/ports/common/guts/execvp.c +++ b/ports/common/guts/execvp.c @@ -20,7 +20,7 @@ } pseudo_setupenv(); - if (pseudo_get_value("PSEUDO_UNLOAD")) + if (pseudo_has_unload(NULL)) pseudo_dropenv(); /* if exec() fails, we may end up taking signals unexpectedly... diff --git a/ports/common/guts/fork.c b/ports/common/guts/fork.c index df8abd7..bebe3b0 100644 --- a/ports/common/guts/fork.c +++ b/ports/common/guts/fork.c @@ -12,7 +12,7 @@ */ if (rc == 0) { pseudo_setupenv(); - if (!pseudo_get_value("PSEUDO_UNLOAD")) { + if (!pseudo_has_unload(NULL)) { pseudo_reinit_libpseudo(); } else { pseudo_dropenv(); diff --git a/ports/linux/newclone/pseudo_wrappers.c b/ports/linux/newclone/pseudo_wrappers.c index 092e532..1fc6c59 100644 --- a/ports/linux/newclone/pseudo_wrappers.c +++ b/ports/linux/newclone/pseudo_wrappers.c @@ -28,7 +28,7 @@ int wrap_clone_child(void *args) { if (!(flags & CLONE_VM)) { pseudo_setupenv(); - if (!pseudo_get_value("PSEUDO_UNLOAD")) { + if (!pseudo_has_unload(NULL)) { pseudo_reinit_libpseudo(); } else { pseudo_dropenv(); diff --git a/ports/linux/oldclone/pseudo_wrappers.c b/ports/linux/oldclone/pseudo_wrappers.c index f0a8eec..1720dfb 100644 --- a/ports/linux/oldclone/pseudo_wrappers.c +++ b/ports/linux/oldclone/pseudo_wrappers.c @@ -22,7 +22,7 @@ int wrap_clone_child(void *args) { if (!(flags & CLONE_VM)) { pseudo_setupenv(); - if (!pseudo_get_value("PSEUDO_UNLOAD")) { + if (!pseudo_has_unload(NULL)) { pseudo_reinit_libpseudo(); } else { pseudo_dropenv(); diff --git a/ports/unix/guts/popen.c b/ports/unix/guts/popen.c index 0ca16b0..5d44c0e 100644 --- a/ports/unix/guts/popen.c +++ b/ports/unix/guts/popen.c @@ -9,7 +9,7 @@ * in ways that avoid our usual enforcement of the environment. */ pseudo_setupenv(); - if (pseudo_get_value("PSEUDO_UNLOAD")) + if (pseudo_has_unload(NULL)) pseudo_dropenv(); rc = real_popen(command, mode); diff --git a/ports/unix/guts/system.c b/ports/unix/guts/system.c index 028b372..6351592 100644 --- a/ports/unix/guts/system.c +++ b/ports/unix/guts/system.c @@ -9,7 +9,7 @@ return 1; pseudo_setupenv(); - if (pseudo_get_value("PSEUDO_UNLOAD")) + if (pseudo_has_unload(NULL)) pseudo_dropenv(); rc = real_system(command); @@ -28,6 +28,7 @@ extern void pseudo_init_client(void); void pseudo_dump_env(char **envp); int pseudo_set_value(const char *key, const char *value); char *pseudo_get_value(const char *key); +int pseudo_has_unload(char * const *envp); #include "pseudo_tables.h" diff --git a/pseudo_util.c b/pseudo_util.c index f20dbec..325cabf 100644 --- a/pseudo_util.c +++ b/pseudo_util.c @@ -95,6 +95,33 @@ dump_env(char **envp) { } #endif +int +pseudo_has_unload(char * const *envp) { + static const char unload[] = "PSEUDO_UNLOAD"; + static size_t unload_len = strlen(unload); + size_t i = 0; + + /* Is it in the caller environment? */ + if (NULL != getenv(unload)) + return 1; + + /* Is it in the environment cache? */ + if (pseudo_util_initted == -1) + pseudo_init_util(); + while (pseudo_env[i].key && strcmp(pseudo_env[i].key, unload)) + ++i; + if (pseudo_env[i].key && pseudo_env[i].value) + return 1; + + /* Is it in the operational environment? */ + while (envp && *envp) { + if ((!strncmp(*envp, unload, unload_len)) && ('=' == (*envp)[unload_len])) + return 1; + ++envp; + } + return 0; +} + /* Caller must free memory! */ char * pseudo_get_value(const char *key) { |