1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// RUN: %clangxx_asan -g -Wno-deprecated-declarations %s -o %t
// RUN: %env_asan_opts=exitcode=42 %run %t | FileCheck %s
// Android doesn't have spawn.h or posix_spawn.
// UNSUPPORTED: android
// CHECK: got expected 42 exit code
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
int spawn_child(char **argv) {
// Set an environment variable to tell the child process to interrupt
// itself.
if (!SetEnvironmentVariableW(L"CRASH_FOR_TEST", L"1")) {
printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError());
fflush(stdout);
exit(1);
}
STARTUPINFOW si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
if (!CreateProcessW(nullptr, // No module name (use command line)
GetCommandLineW(), // Command line
nullptr, // Process handle not inheritable
nullptr, // Thread handle not inheritable
TRUE, // Set handle inheritance to TRUE
0, // No flags
nullptr, // Use parent's environment block
nullptr, // Use parent's starting directory
&si, &pi)) {
printf("CreateProcess failed (0x%08lx).\n", GetLastError());
fflush(stdout);
exit(1);
}
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exit_code;
if (!GetExitCodeProcess(pi.hProcess, &exit_code)) {
printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError());
fflush(stdout);
exit(1);
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return exit_code;
}
#else
#include <spawn.h>
#include <errno.h>
#include <sys/wait.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
#define USE_NSGETENVIRON 1
#else
#define USE_NSGETENVIRON 0
#endif
#if !USE_NSGETENVIRON
extern char **environ;
#else
#include <crt_externs.h> // _NSGetEnviron
#endif
int spawn_child(char **argv) {
setenv("CRASH_FOR_TEST", "1", 1);
#if !USE_NSGETENVIRON
char **envp = environ;
#else
char **envp = *_NSGetEnviron();
#endif
pid_t pid;
int err = posix_spawn(&pid, argv[0], nullptr, nullptr, argv, envp);
if (err) {
printf("posix_spawn failed: %d\n", err);
fflush(stdout);
exit(1);
}
// Wait until the child exits.
int status;
pid_t wait_result_pid;
do {
wait_result_pid = waitpid(pid, &status, 0);
} while (wait_result_pid == -1 && errno == EINTR);
if (wait_result_pid != pid || !WIFEXITED(status)) {
printf("error in waitpid\n");
fflush(stdout);
exit(1);
}
// Return the exit status.
return WEXITSTATUS(status);
}
#endif
int main(int argc, char **argv) {
int r = 0;
if (getenv("CRASH_FOR_TEST")) {
// Generate an asan report to test ASAN_OPTIONS=exitcode=42
int *p = new int;
delete p;
r = *p;
} else {
int exit_code = spawn_child(argv);
if (exit_code == 42) {
printf("got expected 42 exit code\n");
fflush(stdout);
}
}
return r;
}
|