blob: fea09a698b56e31bb2cb7e51184b13cd795bd832 [file] [log] [blame]
Zachary Turner6fa57ad2016-12-02 23:02:01 +00001//===- 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//===----------------------------------------------------------------------===//
Zachary Turner6fa57ad2016-12-02 23:02:01 +000011#include "FuzzerDefs.h"
12#if LIBFUZZER_WINDOWS
13#include "FuzzerIO.h"
14#include "FuzzerInternal.h"
Zachary Turner6fa57ad2016-12-02 23:02:01 +000015#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>
Marcos Pividoric59b6922016-12-13 17:45:20 +000025#include <Psapi.h>
Zachary Turner6fa57ad2016-12-02 23:02:01 +000026
27namespace fuzzer {
28
Marcos Pividoric59b6922016-12-13 17:45:20 +000029static const FuzzingOptions* HandlerOpt = nullptr;
30
31LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
Zachary Turner6fa57ad2016-12-02 23:02:01 +000032 switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
Marcos Pividoric59b6922016-12-13 17:45:20 +000033 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;
Zachary Turner6fa57ad2016-12-02 23:02:01 +000061 }
62 return EXCEPTION_CONTINUE_SEARCH;
63}
64
Marcos Pividoric59b6922016-12-13 17:45:20 +000065BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
Zachary Turner6fa57ad2016-12-02 23:02:01 +000066 switch (dwCtrlType) {
Marcos Pividoric59b6922016-12-13 17:45:20 +000067 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;
Zachary Turner6fa57ad2016-12-02 23:02:01 +000075 }
Marcos Pividoric59b6922016-12-13 17:45:20 +000076 return FALSE;
Zachary Turner6fa57ad2016-12-02 23:02:01 +000077}
78
Marcos Pividori681e9042016-12-12 23:25:11 +000079void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
80 Fuzzer::StaticAlarmCallback();
81}
82
83class TimerQ {
84 HANDLE TimerQueue;
85 public:
86 TimerQ() : TimerQueue(NULL) {};
87 ~TimerQ() {
88 if (TimerQueue)
89 DeleteTimerQueueEx(TimerQueue, NULL);
90 };
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
108static TimerQ Timer;
109
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000110static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
111
Marcos Pividoric59b6922016-12-13 17:45:20 +0000112void SetSignalHandler(const FuzzingOptions& Options) {
113 HandlerOpt = &Options;
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000114
Marcos Pividoric59b6922016-12-13 17:45:20 +0000115 if (Options.UnitTimeoutSec > 0)
116 Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000117
Marcos Pividoric59b6922016-12-13 17:45:20 +0000118 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 }
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000125
Marcos Pividoric59b6922016-12-13 17:45:20 +0000126 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 }
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000132
Marcos Pividoric59b6922016-12-13 17:45:20 +0000133 if (Options.HandleAbrt)
134 if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
135 Printf("libFuzzer: signal failed with %d\n", errno);
136 exit(1);
137 }
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000138}
139
140void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
141
Marcos Pividori463f8bd2016-12-13 17:45:44 +0000142unsigned long GetPid() { return GetCurrentProcessId(); }
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000143
144size_t GetPeakRSSMb() {
145 PROCESS_MEMORY_COUNTERS info;
146 if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
147 return 0;
148 return info.PeakWorkingSetSize >> 20;
149}
150
151FILE *OpenProcessPipe(const char *Command, const char *Mode) {
152 return _popen(Command, Mode);
153}
154
155int ExecuteCommand(const std::string &Command) {
156 return system(Command.c_str());
157}
158
159const 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;
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
Marcos Pividori178fe582016-12-13 17:46:11 +0000181
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000182#endif // LIBFUZZER_WINDOWS