brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.5 KiB · 45ee155 Raw
267 lines · cpp
1//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// Misc utils implementation for Windows.9//===----------------------------------------------------------------------===//10#include "FuzzerPlatform.h"11#if LIBFUZZER_WINDOWS12#include "FuzzerCommand.h"13#include "FuzzerIO.h"14#include "FuzzerInternal.h"15#include <cassert>16#include <chrono>17#include <cstring>18#include <errno.h>19#include <io.h>20#include <iomanip>21#include <signal.h>22#include <stdio.h>23#include <sys/types.h>24// clang-format off25#include <windows.h>26// These must be included after windows.h.27// architecture need to be set before including28// libloaderapi29#include <libloaderapi.h>30#include <stringapiset.h>31#include <psapi.h>32// clang-format on33 34namespace fuzzer {35 36static const FuzzingOptions* HandlerOpt = nullptr;37 38static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {39  switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {40    case EXCEPTION_ACCESS_VIOLATION:41    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:42    case EXCEPTION_STACK_OVERFLOW:43      if (HandlerOpt->HandleSegv)44        Fuzzer::StaticCrashSignalCallback();45      break;46    case EXCEPTION_DATATYPE_MISALIGNMENT:47    case EXCEPTION_IN_PAGE_ERROR:48      if (HandlerOpt->HandleBus)49        Fuzzer::StaticCrashSignalCallback();50      break;51    case EXCEPTION_ILLEGAL_INSTRUCTION:52    case EXCEPTION_PRIV_INSTRUCTION:53      if (HandlerOpt->HandleIll)54        Fuzzer::StaticCrashSignalCallback();55      break;56    case EXCEPTION_FLT_DENORMAL_OPERAND:57    case EXCEPTION_FLT_DIVIDE_BY_ZERO:58    case EXCEPTION_FLT_INEXACT_RESULT:59    case EXCEPTION_FLT_INVALID_OPERATION:60    case EXCEPTION_FLT_OVERFLOW:61    case EXCEPTION_FLT_STACK_CHECK:62    case EXCEPTION_FLT_UNDERFLOW:63    case EXCEPTION_INT_DIVIDE_BY_ZERO:64    case EXCEPTION_INT_OVERFLOW:65      if (HandlerOpt->HandleFpe)66        Fuzzer::StaticCrashSignalCallback();67      break;68    // This is an undocumented exception code corresponding to a Visual C++69    // Exception.70    //71    // See: https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=1327372    case 0xE06D7363:73      if (HandlerOpt->HandleWinExcept)74        Fuzzer::StaticCrashSignalCallback();75      break;76      // TODO: Handle (Options.HandleXfsz)77  }78  return EXCEPTION_CONTINUE_SEARCH;79}80 81BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {82  switch (dwCtrlType) {83    case CTRL_C_EVENT:84      if (HandlerOpt->HandleInt)85        Fuzzer::StaticInterruptCallback();86      return TRUE;87    case CTRL_BREAK_EVENT:88      if (HandlerOpt->HandleTerm)89        Fuzzer::StaticInterruptCallback();90      return TRUE;91  }92  return FALSE;93}94 95void CALLBACK AlarmHandler(PVOID, BOOLEAN) {96  Fuzzer::StaticAlarmCallback();97}98 99class TimerQ {100  HANDLE TimerQueue;101 public:102  TimerQ() : TimerQueue(NULL) {}103  ~TimerQ() {104    if (TimerQueue)105      DeleteTimerQueueEx(TimerQueue, NULL);106  }107  void SetTimer(int Seconds) {108    if (!TimerQueue) {109      TimerQueue = CreateTimerQueue();110      if (!TimerQueue) {111        Printf("libFuzzer: CreateTimerQueue failed.\n");112        exit(1);113      }114    }115    HANDLE Timer;116    if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,117        Seconds*1000, Seconds*1000, 0)) {118      Printf("libFuzzer: CreateTimerQueueTimer failed.\n");119      exit(1);120    }121  }122};123 124static TimerQ Timer;125 126static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }127 128void SetSignalHandler(const FuzzingOptions& Options) {129  HandlerOpt = &Options;130 131  if (Options.HandleAlrm && Options.UnitTimeoutSec > 0)132    Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);133 134  if (Options.HandleInt || Options.HandleTerm)135    if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {136      DWORD LastError = GetLastError();137      Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",138        LastError);139      exit(1);140    }141 142  if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||143      Options.HandleFpe || Options.HandleWinExcept)144    SetUnhandledExceptionFilter(ExceptionHandler);145 146  if (Options.HandleAbrt)147    if (SIG_ERR == signal(SIGABRT, CrashHandler)) {148      Printf("libFuzzer: signal failed with %d\n", errno);149      exit(1);150    }151}152 153void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }154 155unsigned long GetPid() { return GetCurrentProcessId(); }156 157size_t GetPeakRSSMb() {158  PROCESS_MEMORY_COUNTERS info;159  if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))160    return 0;161  return info.PeakWorkingSetSize >> 20;162}163 164FILE *OpenProcessPipe(const char *Command, const char *Mode) {165  return _popen(Command, Mode);166}167 168int CloseProcessPipe(FILE *F) {169  return _pclose(F);170}171 172int ExecuteCommand(const Command &Cmd) {173  std::string CmdLine = Cmd.toString();174  return system(CmdLine.c_str());175}176 177bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) {178  FILE *Pipe = _popen(Cmd.toString().c_str(), "r");179  if (!Pipe)180    return false;181 182  if (CmdOutput) {183    char TmpBuffer[128];184    while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe))185      CmdOutput->append(TmpBuffer);186  }187  return _pclose(Pipe) == 0;188}189 190const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,191                         size_t PattLen) {192  // TODO: make this implementation more efficient.193  const char *Cdata = (const char *)Data;194  const char *Cpatt = (const char *)Patt;195 196  if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)197    return NULL;198 199  if (PattLen == 1)200    return memchr(Data, *Cpatt, DataLen);201 202  const char *End = Cdata + DataLen - PattLen + 1;203 204  for (const char *It = Cdata; It < End; ++It)205    if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)206      return It;207 208  return NULL;209}210 211std::string DisassembleCmd(const std::string &FileName) {212  std::vector<std::string> command_vector;213  command_vector.push_back("dumpbin /summary > nul");214  if (ExecuteCommand(Command(command_vector)) == 0)215    return "dumpbin /disasm " + FileName;216  Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n");217  exit(1);218}219 220std::string SearchRegexCmd(const std::string &Regex) {221  return "findstr /r \"" + Regex + "\"";222}223 224void DiscardOutput(int Fd) {225  FILE* Temp = fopen("nul", "w");226  if (!Temp)227    return;228  _dup2(_fileno(Temp), Fd);229  fclose(Temp);230}231 232size_t PageSize() {233  static size_t PageSizeCached = []() -> size_t {234    SYSTEM_INFO si;235    GetSystemInfo(&si);236    return si.dwPageSize;237  }();238  return PageSizeCached;239}240 241void SetThreadName(std::thread &thread, const std::string &name) {242#ifndef __MINGW32__243  // Not setting the thread name in MinGW environments. MinGW C++ standard244  // libraries can either use native Windows threads or pthreads, so we245  // don't know with certainty what kind of thread handle we're getting246  // from thread.native_handle() here.247  typedef HRESULT(WINAPI * proc)(HANDLE, PCWSTR);248  HMODULE kbase = GetModuleHandleA("KernelBase.dll");249  proc ThreadNameProc = reinterpret_cast<proc>(250      (void *)GetProcAddress(kbase, "SetThreadDescription"));251  if (ThreadNameProc) {252    std::wstring buf;253    auto sz = MultiByteToWideChar(CP_UTF8, 0, name.data(), -1, nullptr, 0);254    if (sz > 0) {255      buf.resize(sz);256      if (MultiByteToWideChar(CP_UTF8, 0, name.data(), -1, &buf[0], sz) > 0) {257        (void)ThreadNameProc(thread.native_handle(), buf.c_str());258      }259    }260  }261#endif262}263 264} // namespace fuzzer265 266#endif // LIBFUZZER_WINDOWS267