Home | History | Annotate | Line # | Download | only in fuzzer
      1 //===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 // Misc utils implementation for Windows.
     10 //===----------------------------------------------------------------------===//
     11 #include "FuzzerDefs.h"
     12 #if LIBFUZZER_WINDOWS
     13 #include "FuzzerCommand.h"
     14 #include "FuzzerIO.h"
     15 #include "FuzzerInternal.h"
     16 #include <cassert>
     17 #include <chrono>
     18 #include <cstring>
     19 #include <errno.h>
     20 #include <iomanip>
     21 #include <signal.h>
     22 #include <stdio.h>
     23 #include <sys/types.h>
     24 #include <windows.h>
     25 
     26 // This must be included after windows.h.
     27 #include <psapi.h>
     28 
     29 namespace fuzzer {
     30 
     31 static const FuzzingOptions* HandlerOpt = nullptr;
     32 
     33 static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
     34   switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
     35     case EXCEPTION_ACCESS_VIOLATION:
     36     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
     37     case EXCEPTION_STACK_OVERFLOW:
     38       if (HandlerOpt->HandleSegv)
     39         Fuzzer::StaticCrashSignalCallback();
     40       break;
     41     case EXCEPTION_DATATYPE_MISALIGNMENT:
     42     case EXCEPTION_IN_PAGE_ERROR:
     43       if (HandlerOpt->HandleBus)
     44         Fuzzer::StaticCrashSignalCallback();
     45       break;
     46     case EXCEPTION_ILLEGAL_INSTRUCTION:
     47     case EXCEPTION_PRIV_INSTRUCTION:
     48       if (HandlerOpt->HandleIll)
     49         Fuzzer::StaticCrashSignalCallback();
     50       break;
     51     case EXCEPTION_FLT_DENORMAL_OPERAND:
     52     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
     53     case EXCEPTION_FLT_INEXACT_RESULT:
     54     case EXCEPTION_FLT_INVALID_OPERATION:
     55     case EXCEPTION_FLT_OVERFLOW:
     56     case EXCEPTION_FLT_STACK_CHECK:
     57     case EXCEPTION_FLT_UNDERFLOW:
     58     case EXCEPTION_INT_DIVIDE_BY_ZERO:
     59     case EXCEPTION_INT_OVERFLOW:
     60       if (HandlerOpt->HandleFpe)
     61         Fuzzer::StaticCrashSignalCallback();
     62       break;
     63     // TODO: handle (Options.HandleXfsz)
     64   }
     65   return EXCEPTION_CONTINUE_SEARCH;
     66 }
     67 
     68 BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
     69   switch (dwCtrlType) {
     70     case CTRL_C_EVENT:
     71       if (HandlerOpt->HandleInt)
     72         Fuzzer::StaticInterruptCallback();
     73       return TRUE;
     74     case CTRL_BREAK_EVENT:
     75       if (HandlerOpt->HandleTerm)
     76         Fuzzer::StaticInterruptCallback();
     77       return TRUE;
     78   }
     79   return FALSE;
     80 }
     81 
     82 void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
     83   Fuzzer::StaticAlarmCallback();
     84 }
     85 
     86 class TimerQ {
     87   HANDLE TimerQueue;
     88  public:
     89   TimerQ() : TimerQueue(NULL) {};
     90   ~TimerQ() {
     91     if (TimerQueue)
     92       DeleteTimerQueueEx(TimerQueue, NULL);
     93   };
     94   void SetTimer(int Seconds) {
     95     if (!TimerQueue) {
     96       TimerQueue = CreateTimerQueue();
     97       if (!TimerQueue) {
     98         Printf("libFuzzer: CreateTimerQueue failed.\n");
     99         exit(1);
    100       }
    101     }
    102     HANDLE Timer;
    103     if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
    104         Seconds*1000, Seconds*1000, 0)) {
    105       Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
    106       exit(1);
    107     }
    108   };
    109 };
    110 
    111 static TimerQ Timer;
    112 
    113 static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
    114 
    115 void SetSignalHandler(const FuzzingOptions& Options) {
    116   HandlerOpt = &Options;
    117 
    118   if (Options.UnitTimeoutSec > 0)
    119     Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
    120 
    121   if (Options.HandleInt || Options.HandleTerm)
    122     if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
    123       DWORD LastError = GetLastError();
    124       Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
    125         LastError);
    126       exit(1);
    127     }
    128 
    129   if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
    130       Options.HandleFpe)
    131     SetUnhandledExceptionFilter(ExceptionHandler);
    132 
    133   if (Options.HandleAbrt)
    134     if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
    135       Printf("libFuzzer: signal failed with %d\n", errno);
    136       exit(1);
    137     }
    138 }
    139 
    140 void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
    141 
    142 unsigned long GetPid() { return GetCurrentProcessId(); }
    143 
    144 size_t GetPeakRSSMb() {
    145   PROCESS_MEMORY_COUNTERS info;
    146   if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
    147     return 0;
    148   return info.PeakWorkingSetSize >> 20;
    149 }
    150 
    151 FILE *OpenProcessPipe(const char *Command, const char *Mode) {
    152   return _popen(Command, Mode);
    153 }
    154 
    155 int ExecuteCommand(const Command &Cmd) {
    156   std::string CmdLine = Cmd.toString();
    157   return system(CmdLine.c_str());
    158 }
    159 
    160 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
    161                          size_t PattLen) {
    162   // TODO: make this implementation more efficient.
    163   const char *Cdata = (const char *)Data;
    164   const char *Cpatt = (const char *)Patt;
    165 
    166   if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
    167     return NULL;
    168 
    169   if (PattLen == 1)
    170     return memchr(Data, *Cpatt, DataLen);
    171 
    172   const char *End = Cdata + DataLen - PattLen + 1;
    173 
    174   for (const char *It = Cdata; It < End; ++It)
    175     if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
    176       return It;
    177 
    178   return NULL;
    179 }
    180 
    181 std::string DisassembleCmd(const std::string &FileName) {
    182   Vector<std::string> command_vector;
    183   command_vector.push_back("dumpbin /summary > nul");
    184   if (ExecuteCommand(Command(command_vector)) == 0)
    185     return "dumpbin /disasm " + FileName;
    186   Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n");
    187   exit(1);
    188 }
    189 
    190 std::string SearchRegexCmd(const std::string &Regex) {
    191   return "findstr /r \"" + Regex + "\"";
    192 }
    193 
    194 } // namespace fuzzer
    195 
    196 #endif // LIBFUZZER_WINDOWS
    197