brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · 0faa2ff Raw
131 lines · cpp
1// RUN: %clang_cl_asan -Od %p/../dll_host.cpp -Fe%t2// RUN: %clang_cl_asan -LD -O2 %s -Fe%t.dll3// RUNX: %run %t %t.dll 2>&1 | FileCheck %s4 5// Check that ASan does not CHECK fail when SEH is used around a crash from a6// thread injected by control C.7 8#include <stdio.h>9#include <stdlib.h>10#include <windows.h>11 12static void __declspec(noinline) CrashOnProcessDetach() {13  printf("CrashOnProcessDetach\n");14  fflush(stdout);15  *static_cast<volatile int *>(0) = 0x356;16}17 18bool g_is_child = false;19 20BOOL WINAPI DllMain(PVOID h, DWORD reason, PVOID reserved) {21  if (reason == DLL_PROCESS_DETACH && g_is_child) {22    printf("in DllMain DLL_PROCESS_DETACH\n");23    fflush(stdout);24    __try {25      CrashOnProcessDetach();26    } __except (1) {27      printf("caught crash\n");28      fflush(stdout);29    }30  }31  return true;32}33 34static void run_child() {35  // Send this process group Ctrl+C. That should only be this process.36  printf("GenerateConsoleCtrlEvent\n");37  fflush(stdout);38  GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);39  Sleep(10 * 1000); // Wait 10 seconds, and the process should die.40  printf("unexpected execution after interrupt\n");41  fflush(stdout);42  exit(0x42);43}44 45static int WINAPI ignore_control_c(DWORD ctrl_type) {46  // Don't interrupt the parent.47  return ctrl_type == CTRL_C_EVENT;48}49 50static int run_parent() {51  // Set an environment variable to tell the child process to interrupt itself.52  if (!SetEnvironmentVariableW(L"DO_CONTROL_C", L"1")) {53    printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError());54    fflush(stdout);55    return 2;56  }57 58  // Launch a new process using the current executable with a new console.59  // Ctrl-C events are console-wide, so we need a new console.60  STARTUPINFOW si;61  memset(&si, 0, sizeof(si));62  si.cb = sizeof(si);63  // Hides the new console window that we are creating.64  si.dwFlags |= STARTF_USESHOWWINDOW;65  si.wShowWindow = SW_HIDE;66  // Ensures that stdout still goes to the parent despite the new console.67  si.dwFlags |= STARTF_USESTDHANDLES;68  si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);69  si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);70  si.hStdError = GetStdHandle(STD_ERROR_HANDLE);71 72  PROCESS_INFORMATION pi;73  memset(&pi, 0, sizeof(pi));74  int flags = CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE;75  if (!CreateProcessW(nullptr,           // No module name (use command line)76                      GetCommandLineW(), // Command line77                      nullptr,           // Process handle not inheritable78                      nullptr,           // Thread handle not inheritable79                      TRUE,              // Set handle inheritance to TRUE80                      flags,             // Flags to give the child a console81                      nullptr,           // Use parent's environment block82                      nullptr,           // Use parent's starting directory83                      &si, &pi)) {84    printf("CreateProcess failed (0x%08lx).\n", GetLastError());85    fflush(stdout);86    return 2;87  }88 89  // Wait until child process exits.90  if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) {91    printf("WaitForSingleObject failed (0x%08lx).\n", GetLastError());92    fflush(stdout);93    return 2;94  }95 96  // Get the exit code. It should be the one for ctrl-c events.97  DWORD rc;98  if (!GetExitCodeProcess(pi.hProcess, &rc)) {99    printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError());100    fflush(stdout);101    return 2;102  }103  if (rc == STATUS_CONTROL_C_EXIT)104    printf("child quit with STATUS_CONTROL_C_EXIT\n");105  else106    printf("unexpected exit code: 0x%08lx\n", rc);107  fflush(stdout);108 109  // Close process and thread handles.110  CloseHandle(pi.hProcess);111  CloseHandle(pi.hThread);112  return 0;113}114 115// CHECK: in DllMain DLL_PROCESS_DETACH116// CHECK: CrashOnProcessDetach117// CHECK: caught crash118// CHECK: child quit with STATUS_CONTROL_C_EXIT119 120extern "C" int __declspec(dllexport) test_function() {121  wchar_t buf[260];122  int len = GetEnvironmentVariableW(L"DO_CONTROL_C", buf, 260);123  if (len > 0) {124    g_is_child = true;125    run_child();126  } else {127    exit(run_parent());128  }129  return 0;130}131