env_interposer.cpp (2164B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include <pthread.h> 6 #include <string.h> 7 #include <unistd.h> 8 9 #include "InterposerHelper.h" 10 11 // The interposers in this file cover all the functions used to access the 12 // environment (getenv(), putenv(), setenv(), unsetenv() and clearenv()). They 13 // all use the mutex below for synchronization to prevent races that caused 14 // startup crashes, see bug 1752703. 15 static pthread_mutex_t gEnvLock = PTHREAD_MUTEX_INITIALIZER; 16 17 static char* internal_getenv(const char* aName) { 18 if (environ == nullptr || aName[0] == '\0') { 19 return nullptr; 20 } 21 22 size_t len = strlen(aName); 23 for (char** env_ptr = environ; *env_ptr != nullptr; ++env_ptr) { 24 if ((aName[0] == (*env_ptr)[0]) && (strncmp(aName, *env_ptr, len) == 0) && 25 ((*env_ptr)[len] == '=')) { 26 return *env_ptr + len + 1; 27 } 28 } 29 30 return nullptr; 31 } 32 33 extern "C" { 34 35 MFBT_API char* getenv(const char* name) { 36 pthread_mutex_lock(&gEnvLock); 37 char* result = internal_getenv(name); 38 pthread_mutex_unlock(&gEnvLock); 39 40 return result; 41 } 42 43 MFBT_API int putenv(char* string) { 44 static const auto real_putenv = GET_REAL_SYMBOL(putenv); 45 46 pthread_mutex_lock(&gEnvLock); 47 int result = real_putenv(string); 48 pthread_mutex_unlock(&gEnvLock); 49 return result; 50 } 51 52 MFBT_API int setenv(const char* name, const char* value, int replace) { 53 static const auto real_setenv = GET_REAL_SYMBOL(setenv); 54 55 pthread_mutex_lock(&gEnvLock); 56 int result = real_setenv(name, value, replace); 57 pthread_mutex_unlock(&gEnvLock); 58 return result; 59 } 60 61 MFBT_API int unsetenv(const char* name) { 62 static const auto real_unsetenv = GET_REAL_SYMBOL(unsetenv); 63 64 pthread_mutex_lock(&gEnvLock); 65 int result = real_unsetenv(name); 66 pthread_mutex_unlock(&gEnvLock); 67 return result; 68 } 69 70 MFBT_API int clearenv(void) { 71 static const auto real_clearenv = GET_REAL_SYMBOL(clearenv); 72 73 pthread_mutex_lock(&gEnvLock); 74 int result = real_clearenv(); 75 pthread_mutex_unlock(&gEnvLock); 76 return result; 77 } 78 79 } // extern "C"