summaryrefslogtreecommitdiffstats
path: root/mozglue/interposers/env_interposer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mozglue/interposers/env_interposer.cpp')
-rw-r--r--mozglue/interposers/env_interposer.cpp79
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"