diff --git a/mozglue/interposers/env_interposer.cpp b/mozglue/interposers/env_interposer.cpp new file mode 100644 index 0000000000000..cf41f6a333b22 --- /dev/null +++ b/mozglue/interposers/env_interposer.cpp @@ -0,0 +1,78 @@ +/* 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 +#include + +#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" diff --git a/mozglue/interposers/moz.build b/mozglue/interposers/moz.build index 36c49670089bb..f191deff8fc96 100644 --- a/mozglue/interposers/moz.build +++ b/mozglue/interposers/moz.build @@ -7,6 +7,10 @@ Library("interposers") DEFINES["IMPL_MFBT"] = True +UNIFIED_SOURCES += [ + "env_interposer.cpp", +] + if CONFIG["MOZ_CRASHREPORTER"]: UNIFIED_SOURCES += [ "pthread_create_interposer.cpp",