blob: f2dd6e6cca0228e9430f922f601746031c6cb198 [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//===----------------------------------------------------------------------===//
11
12#include "FuzzerDefs.h"
13#if LIBFUZZER_WINDOWS
14#include "FuzzerIO.h"
15#include "FuzzerInternal.h"
Zachary Turner6fa57ad2016-12-02 23:02:01 +000016#include <cassert>
17#include <chrono>
18#include <cstring>
19#include <errno.h>
20#include <iomanip>
21#include <signal.h>
22#include <sstream>
23#include <stdio.h>
24#include <sys/types.h>
25#include <windows.h>
Marcos Pividoric59b6922016-12-13 17:45:20 +000026#include <Psapi.h>
Zachary Turner6fa57ad2016-12-02 23:02:01 +000027
28namespace fuzzer {
29
Marcos Pividoric59b6922016-12-13 17:45:20 +000030static const FuzzingOptions* HandlerOpt = nullptr;
31
32LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
Zachary Turner6fa57ad2016-12-02 23:02:01 +000033 switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
Marcos Pividoric59b6922016-12-13 17:45:20 +000034 case EXCEPTION_ACCESS_VIOLATION:
35 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
36 case EXCEPTION_STACK_OVERFLOW:
37 if (HandlerOpt->HandleSegv)
38 Fuzzer::StaticCrashSignalCallback();
39 break;
40 case EXCEPTION_DATATYPE_MISALIGNMENT:
41 case EXCEPTION_IN_PAGE_ERROR:
42 if (HandlerOpt->HandleBus)
43 Fuzzer::StaticCrashSignalCallback();
44 break;
45 case EXCEPTION_ILLEGAL_INSTRUCTION:
46 case EXCEPTION_PRIV_INSTRUCTION:
47 if (HandlerOpt->HandleIll)
48 Fuzzer::StaticCrashSignalCallback();
49 break;
50 case EXCEPTION_FLT_DENORMAL_OPERAND:
51 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
52 case EXCEPTION_FLT_INEXACT_RESULT:
53 case EXCEPTION_FLT_INVALID_OPERATION:
54 case EXCEPTION_FLT_OVERFLOW:
55 case EXCEPTION_FLT_STACK_CHECK:
56 case EXCEPTION_FLT_UNDERFLOW:
57 case EXCEPTION_INT_DIVIDE_BY_ZERO:
58 case EXCEPTION_INT_OVERFLOW:
59 if (HandlerOpt->HandleFpe)
60 Fuzzer::StaticCrashSignalCallback();
61 break;
Zachary Turner6fa57ad2016-12-02 23:02:01 +000062 }
63 return EXCEPTION_CONTINUE_SEARCH;
64}
65
Marcos Pividoric59b6922016-12-13 17:45:20 +000066BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
Zachary Turner6fa57ad2016-12-02 23:02:01 +000067 switch (dwCtrlType) {
Marcos Pividoric59b6922016-12-13 17:45:20 +000068 case CTRL_C_EVENT:
69 if (HandlerOpt->HandleInt)
70 Fuzzer::StaticInterruptCallback();
71 return TRUE;
72 case CTRL_BREAK_EVENT:
73 if (HandlerOpt->HandleTerm)
74 Fuzzer::StaticInterruptCallback();
75 return TRUE;
Zachary Turner6fa57ad2016-12-02 23:02:01 +000076 }
Marcos Pividoric59b6922016-12-13 17:45:20 +000077 return FALSE;
Zachary Turner6fa57ad2016-12-02 23:02:01 +000078}
79
Marcos Pividori681e9042016-12-12 23:25:11 +000080void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
81 Fuzzer::StaticAlarmCallback();
82}
83
84class TimerQ {
85 HANDLE TimerQueue;
86 public:
87 TimerQ() : TimerQueue(NULL) {};
88 ~TimerQ() {
89 if (TimerQueue)
90 DeleteTimerQueueEx(TimerQueue, NULL);
91 };
92 void SetTimer(int Seconds) {
93 if (!TimerQueue) {
94 TimerQueue = CreateTimerQueue();
95 if (!TimerQueue) {
96 Printf("libFuzzer: CreateTimerQueue failed.\n");
97 exit(1);
98 }
99 }
100 HANDLE Timer;
101 if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
102 Seconds*1000, Seconds*1000, 0)) {
103 Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
104 exit(1);
105 }
106 };
107};
108
109static TimerQ Timer;
110
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000111static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
112
Marcos Pividoric59b6922016-12-13 17:45:20 +0000113void SetSignalHandler(const FuzzingOptions& Options) {
114 HandlerOpt = &Options;
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000115
Marcos Pividoric59b6922016-12-13 17:45:20 +0000116 if (Options.UnitTimeoutSec > 0)
117 Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000118
Marcos Pividoric59b6922016-12-13 17:45:20 +0000119 if (Options.HandleInt || Options.HandleTerm)
120 if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
121 DWORD LastError = GetLastError();
122 Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
123 LastError);
124 exit(1);
125 }
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000126
Marcos Pividoric59b6922016-12-13 17:45:20 +0000127 if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
128 Options.HandleFpe)
129 if (!AddVectoredExceptionHandler(1, ExceptionHandler)) {
130 Printf("libFuzzer: AddVectoredExceptionHandler failed.\n");
131 exit(1);
132 }
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000133
Marcos Pividoric59b6922016-12-13 17:45:20 +0000134 if (Options.HandleAbrt)
135 if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
136 Printf("libFuzzer: signal failed with %d\n", errno);
137 exit(1);
138 }
Zachary Turner6fa57ad2016-12-02 23:02:01 +0000139}
140
141void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
142
143int GetPid() { return GetCurrentProcessId(); }
144
145size_t GetPeakRSSMb() {
146 PROCESS_MEMORY_COUNTERS info;
147 if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
148 return 0;
149 return info.PeakWorkingSetSize >> 20;
150}
151
152FILE *OpenProcessPipe(const char *Command, const char *Mode) {
153 return _popen(Command, Mode);
154}
155
156int ExecuteCommand(const std::string &Command) {
157 return system(Command.c_str());
158}
159
160const 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;
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} // namespace fuzzer
182#endif // LIBFUZZER_WINDOWS