Avoid using environ on FreeBSD
WebKit passes -Wl,--no-undefined to the compiler when linking shared libraries. This is usually a good practice, but it causes gtest to fail to link because of the use of environ. FreeBSD puts environ symbol in crt1.o instead of libc.so, so the linker is unable to find environ when linking a shared library. Fortunately, there is an easy way to fix it. Since the only use of environ in gtest is to pass it to execve, we can simply replace execve with execv to avoid the need of environ. execv is usually a simple wrapper around execve, so it should be safe to use. This problem was found and reported more than three years ago. The same fix is already committed to WebKit and we don't see any problem reports caused by the change. https://bugs.webkit.org/show_bug.cgi?id=138420 https://trac.webkit.org/changeset/194501/webkit https://bugs.webkit.org/show_bug.cgi?id=208409 https://trac.webkit.org/changeset/257691/webkit https://groups.google.com/forum/#!topic/googletestframework/wrrMj_fmXMc
This commit is contained in:
parent
8567b09290
commit
2e8ebe69dc
@ -1225,21 +1225,9 @@ struct ExecDeathTestArgs {
|
|||||||
int close_fd; // File descriptor to close; the read end of a pipe
|
int close_fd; // File descriptor to close; the read end of a pipe
|
||||||
};
|
};
|
||||||
|
|
||||||
# if GTEST_OS_MAC
|
# if GTEST_OS_QNX
|
||||||
inline char** GetEnviron() {
|
|
||||||
// When Google Test is built as a framework on MacOS X, the environ variable
|
|
||||||
// is unavailable. Apple's documentation (man environ) recommends using
|
|
||||||
// _NSGetEnviron() instead.
|
|
||||||
return *_NSGetEnviron();
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
// Some POSIX platforms expect you to declare environ. extern "C" makes
|
|
||||||
// it reside in the global namespace.
|
|
||||||
extern "C" char** environ;
|
extern "C" char** environ;
|
||||||
inline char** GetEnviron() { return environ; }
|
# else // GTEST_OS_QNX
|
||||||
# endif // GTEST_OS_MAC
|
|
||||||
|
|
||||||
# if !GTEST_OS_QNX
|
|
||||||
// The main function for a threadsafe-style death test child process.
|
// The main function for a threadsafe-style death test child process.
|
||||||
// This function is called in a clone()-ed process and thus must avoid
|
// This function is called in a clone()-ed process and thus must avoid
|
||||||
// any potentially unsafe operations like malloc or libc functions.
|
// any potentially unsafe operations like malloc or libc functions.
|
||||||
@ -1259,18 +1247,18 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can safely call execve() as it's a direct system call. We
|
// We can safely call execv() as it's almost a direct system call. We
|
||||||
// cannot use execvp() as it's a libc function and thus potentially
|
// cannot use execvp() as it's a libc function and thus potentially
|
||||||
// unsafe. Since execve() doesn't search the PATH, the user must
|
// unsafe. Since execv() doesn't search the PATH, the user must
|
||||||
// invoke the test program via a valid path that contains at least
|
// invoke the test program via a valid path that contains at least
|
||||||
// one path separator.
|
// one path separator.
|
||||||
execve(args->argv[0], args->argv, GetEnviron());
|
execv(args->argv[0], args->argv);
|
||||||
DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
|
DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
|
||||||
original_dir + " failed: " +
|
original_dir + " failed: " +
|
||||||
GetLastErrnoDescription());
|
GetLastErrnoDescription());
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
# endif // !GTEST_OS_QNX
|
# endif // GTEST_OS_QNX
|
||||||
|
|
||||||
# if GTEST_HAS_CLONE
|
# if GTEST_HAS_CLONE
|
||||||
// Two utility routines that together determine the direction the stack
|
// Two utility routines that together determine the direction the stack
|
||||||
@ -1339,8 +1327,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
|||||||
fd_flags | FD_CLOEXEC));
|
fd_flags | FD_CLOEXEC));
|
||||||
struct inheritance inherit = {0};
|
struct inheritance inherit = {0};
|
||||||
// spawn is a system call.
|
// spawn is a system call.
|
||||||
child_pid =
|
child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ);
|
||||||
spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron());
|
|
||||||
// Restores the current working directory.
|
// Restores the current working directory.
|
||||||
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||||
|
Loading…
Reference in New Issue
Block a user