diff options
Diffstat (limited to 'mozglue/interposers/env_interposer.cpp')
-rw-r--r-- | mozglue/interposers/env_interposer.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/mozglue/interposers/env_interposer.cpp b/mozglue/interposers/env_interposer.cpp new file mode 100644 index 0000000000..d8c11b5d35 --- /dev/null +++ b/mozglue/interposers/env_interposer.cpp @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <pthread.h> +#include <string.h> +#include <unistd.h> + +#include "InterposerHelper.h" + +// The interposers in this file cover all the functions used to access the +// environment (getenv(), putenv(), setenv(), unsetenv() and clearenv()). They +// all use the mutex below for synchronization to prevent races that caused +// startup crashes, see bug 1752703. +static pthread_mutex_t gEnvLock = PTHREAD_MUTEX_INITIALIZER; + +static char* internal_getenv(const char* aName) { + if (environ == nullptr || aName[0] == '\0') { + return nullptr; + } + + size_t len = strlen(aName); + for (char** env_ptr = environ; *env_ptr != nullptr; ++env_ptr) { + if ((aName[0] == (*env_ptr)[0]) && (strncmp(aName, *env_ptr, len) == 0) && + ((*env_ptr)[len] == '=')) { + return *env_ptr + len + 1; + } + } + + return nullptr; +} + +extern "C" { + +MFBT_API char* getenv(const char* name) { + pthread_mutex_lock(&gEnvLock); + char* result = internal_getenv(name); + pthread_mutex_unlock(&gEnvLock); + + return result; +} + +MFBT_API int putenv(char* string) { + static const auto real_putenv = GET_REAL_SYMBOL(putenv); + + pthread_mutex_lock(&gEnvLock); + int result = real_putenv(string); + pthread_mutex_unlock(&gEnvLock); + return result; +} + +MFBT_API int setenv(const char* name, const char* value, int replace) { + static const auto real_setenv = GET_REAL_SYMBOL(setenv); + + pthread_mutex_lock(&gEnvLock); + int result = real_setenv(name, value, replace); + pthread_mutex_unlock(&gEnvLock); + return result; +} + +MFBT_API int unsetenv(const char* name) { + static const auto real_unsetenv = GET_REAL_SYMBOL(unsetenv); + + pthread_mutex_lock(&gEnvLock); + int result = real_unsetenv(name); + pthread_mutex_unlock(&gEnvLock); + return result; +} + +MFBT_API int clearenv(void) { + static const auto real_clearenv = GET_REAL_SYMBOL(clearenv); + + pthread_mutex_lock(&gEnvLock); + int result = real_clearenv(); + pthread_mutex_unlock(&gEnvLock); + return result; +} + +} // extern "C" |