• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "FuzzerIO.h"
14  #include "FuzzerInternal.h"
15  #include <cassert>
16  #include <chrono>
17  #include <cstring>
18  #include <errno.h>
19  #include <iomanip>
20  #include <signal.h>
21  #include <sstream>
22  #include <stdio.h>
23  #include <sys/types.h>
24  #include <windows.h>
25  #include <Psapi.h>
26  
27  namespace fuzzer {
28  
29  static const FuzzingOptions* HandlerOpt = nullptr;
30  
ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)31  LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
32    switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
33      case EXCEPTION_ACCESS_VIOLATION:
34      case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
35      case EXCEPTION_STACK_OVERFLOW:
36        if (HandlerOpt->HandleSegv)
37          Fuzzer::StaticCrashSignalCallback();
38        break;
39      case EXCEPTION_DATATYPE_MISALIGNMENT:
40      case EXCEPTION_IN_PAGE_ERROR:
41        if (HandlerOpt->HandleBus)
42          Fuzzer::StaticCrashSignalCallback();
43        break;
44      case EXCEPTION_ILLEGAL_INSTRUCTION:
45      case EXCEPTION_PRIV_INSTRUCTION:
46        if (HandlerOpt->HandleIll)
47          Fuzzer::StaticCrashSignalCallback();
48        break;
49      case EXCEPTION_FLT_DENORMAL_OPERAND:
50      case EXCEPTION_FLT_DIVIDE_BY_ZERO:
51      case EXCEPTION_FLT_INEXACT_RESULT:
52      case EXCEPTION_FLT_INVALID_OPERATION:
53      case EXCEPTION_FLT_OVERFLOW:
54      case EXCEPTION_FLT_STACK_CHECK:
55      case EXCEPTION_FLT_UNDERFLOW:
56      case EXCEPTION_INT_DIVIDE_BY_ZERO:
57      case EXCEPTION_INT_OVERFLOW:
58        if (HandlerOpt->HandleFpe)
59          Fuzzer::StaticCrashSignalCallback();
60        break;
61    }
62    return EXCEPTION_CONTINUE_SEARCH;
63  }
64  
CtrlHandler(DWORD dwCtrlType)65  BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
66    switch (dwCtrlType) {
67      case CTRL_C_EVENT:
68        if (HandlerOpt->HandleInt)
69          Fuzzer::StaticInterruptCallback();
70        return TRUE;
71      case CTRL_BREAK_EVENT:
72        if (HandlerOpt->HandleTerm)
73          Fuzzer::StaticInterruptCallback();
74        return TRUE;
75    }
76    return FALSE;
77  }
78  
AlarmHandler(PVOID,BOOLEAN)79  void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
80    Fuzzer::StaticAlarmCallback();
81  }
82  
83  class TimerQ {
84    HANDLE TimerQueue;
85   public:
TimerQ()86    TimerQ() : TimerQueue(NULL) {};
~TimerQ()87    ~TimerQ() {
88      if (TimerQueue)
89        DeleteTimerQueueEx(TimerQueue, NULL);
90    };
SetTimer(int Seconds)91    void SetTimer(int Seconds) {
92      if (!TimerQueue) {
93        TimerQueue = CreateTimerQueue();
94        if (!TimerQueue) {
95          Printf("libFuzzer: CreateTimerQueue failed.\n");
96          exit(1);
97        }
98      }
99      HANDLE Timer;
100      if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
101          Seconds*1000, Seconds*1000, 0)) {
102        Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
103        exit(1);
104      }
105    };
106  };
107  
108  static TimerQ Timer;
109  
CrashHandler(int)110  static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
111  
SetSignalHandler(const FuzzingOptions & Options)112  void SetSignalHandler(const FuzzingOptions& Options) {
113    HandlerOpt = &Options;
114  
115    if (Options.UnitTimeoutSec > 0)
116      Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
117  
118    if (Options.HandleInt || Options.HandleTerm)
119      if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
120        DWORD LastError = GetLastError();
121        Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
122          LastError);
123        exit(1);
124      }
125  
126    if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
127        Options.HandleFpe)
128      if (!AddVectoredExceptionHandler(1, ExceptionHandler)) {
129        Printf("libFuzzer: AddVectoredExceptionHandler failed.\n");
130        exit(1);
131      }
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  
SleepSeconds(int Seconds)140  void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
141  
GetPid()142  unsigned long GetPid() { return GetCurrentProcessId(); }
143  
GetPeakRSSMb()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  
OpenProcessPipe(const char * Command,const char * Mode)151  FILE *OpenProcessPipe(const char *Command, const char *Mode) {
152    return _popen(Command, Mode);
153  }
154  
ExecuteCommand(const std::string & Command)155  int ExecuteCommand(const std::string &Command) {
156    return system(Command.c_str());
157  }
158  
SearchMemory(const void * Data,size_t DataLen,const void * Patt,size_t PattLen)159  const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
160                           size_t PattLen) {
161    // TODO: make this implementation more efficient.
162    const char *Cdata = (const char *)Data;
163    const char *Cpatt = (const char *)Patt;
164  
165    if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
166      return NULL;
167  
168    if (PattLen == 1)
169      return memchr(Data, *Cpatt, DataLen);
170  
171    const char *End = Cdata + DataLen - PattLen + 1;
172  
173    for (const char *It = Cdata; It < End; ++It)
174      if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
175        return It;
176  
177    return NULL;
178  }
179  
180  } // namespace fuzzer
181  
182  #endif // LIBFUZZER_WINDOWS
183