blob: 074e1eb423094ca5492b64a6527f64d116bdb918 [file] [log] [blame]
george.karpenkov29efa6d2017-08-21 23:25:50 +00001//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//
2//
chandlerc40284492019-01-19 08:50:56 +00003// 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-exception
george.karpenkov29efa6d2017-08-21 23:25:50 +00006//
7//===----------------------------------------------------------------------===//
8// Misc utils implementation for Windows.
9//===----------------------------------------------------------------------===//
10#include "FuzzerDefs.h"
11#if LIBFUZZER_WINDOWS
morehousea80f6452017-12-04 19:25:59 +000012#include "FuzzerCommand.h"
george.karpenkov29efa6d2017-08-21 23:25:50 +000013#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>
george.karpenkov29efa6d2017-08-21 23:25:50 +000021#include <stdio.h>
22#include <sys/types.h>
23#include <windows.h>
24
25// This must be included after windows.h.
mstorsjoa2d200e2018-09-11 19:11:54 +000026#include <psapi.h>
george.karpenkov29efa6d2017-08-21 23:25:50 +000027
28namespace fuzzer {
29
30static const FuzzingOptions* HandlerOpt = nullptr;
31
32static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
33 switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
34 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;
62 // TODO: handle (Options.HandleXfsz)
63 }
64 return EXCEPTION_CONTINUE_SEARCH;
65}
66
67BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
68 switch (dwCtrlType) {
69 case CTRL_C_EVENT:
70 if (HandlerOpt->HandleInt)
71 Fuzzer::StaticInterruptCallback();
72 return TRUE;
73 case CTRL_BREAK_EVENT:
74 if (HandlerOpt->HandleTerm)
75 Fuzzer::StaticInterruptCallback();
76 return TRUE;
77 }
78 return FALSE;
79}
80
81void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
82 Fuzzer::StaticAlarmCallback();
83}
84
85class TimerQ {
86 HANDLE TimerQueue;
87 public:
metzman538f9f92019-02-26 17:46:13 +000088 TimerQ() : TimerQueue(NULL) {}
george.karpenkov29efa6d2017-08-21 23:25:50 +000089 ~TimerQ() {
90 if (TimerQueue)
91 DeleteTimerQueueEx(TimerQueue, NULL);
metzman538f9f92019-02-26 17:46:13 +000092 }
george.karpenkov29efa6d2017-08-21 23:25:50 +000093 void SetTimer(int Seconds) {
94 if (!TimerQueue) {
95 TimerQueue = CreateTimerQueue();
96 if (!TimerQueue) {
97 Printf("libFuzzer: CreateTimerQueue failed.\n");
98 exit(1);
99 }
100 }
101 HANDLE Timer;
102 if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
103 Seconds*1000, Seconds*1000, 0)) {
104 Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
105 exit(1);
106 }
metzman538f9f92019-02-26 17:46:13 +0000107 }
george.karpenkov29efa6d2017-08-21 23:25:50 +0000108};
109
110static TimerQ Timer;
111
112static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
113
kccda168932019-01-31 00:09:43 +0000114bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
115 return false; // UNIMPLEMENTED
116}
117
george.karpenkov29efa6d2017-08-21 23:25:50 +0000118void SetSignalHandler(const FuzzingOptions& Options) {
119 HandlerOpt = &Options;
120
121 if (Options.UnitTimeoutSec > 0)
122 Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
123
124 if (Options.HandleInt || Options.HandleTerm)
125 if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
126 DWORD LastError = GetLastError();
127 Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
128 LastError);
129 exit(1);
130 }
131
132 if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
133 Options.HandleFpe)
134 SetUnhandledExceptionFilter(ExceptionHandler);
135
136 if (Options.HandleAbrt)
137 if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
138 Printf("libFuzzer: signal failed with %d\n", errno);
139 exit(1);
140 }
141}
142
143void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
144
145unsigned long GetPid() { return GetCurrentProcessId(); }
146
147size_t GetPeakRSSMb() {
148 PROCESS_MEMORY_COUNTERS info;
149 if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
150 return 0;
151 return info.PeakWorkingSetSize >> 20;
152}
153
154FILE *OpenProcessPipe(const char *Command, const char *Mode) {
155 return _popen(Command, Mode);
156}
157
morehousea80f6452017-12-04 19:25:59 +0000158int ExecuteCommand(const Command &Cmd) {
159 std::string CmdLine = Cmd.toString();
160 return system(CmdLine.c_str());
george.karpenkov29efa6d2017-08-21 23:25:50 +0000161}
162
163const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
164 size_t PattLen) {
165 // TODO: make this implementation more efficient.
166 const char *Cdata = (const char *)Data;
167 const char *Cpatt = (const char *)Patt;
168
169 if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
170 return NULL;
171
172 if (PattLen == 1)
173 return memchr(Data, *Cpatt, DataLen);
174
175 const char *End = Cdata + DataLen - PattLen + 1;
176
177 for (const char *It = Cdata; It < End; ++It)
178 if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
179 return It;
180
181 return NULL;
182}
183
184std::string DisassembleCmd(const std::string &FileName) {
morehouse68f46432018-08-30 15:54:44 +0000185 Vector<std::string> command_vector;
186 command_vector.push_back("dumpbin /summary > nul");
187 if (ExecuteCommand(Command(command_vector)) == 0)
george.karpenkov29efa6d2017-08-21 23:25:50 +0000188 return "dumpbin /disasm " + FileName;
189 Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n");
190 exit(1);
191}
192
193std::string SearchRegexCmd(const std::string &Regex) {
194 return "findstr /r \"" + Regex + "\"";
195}
196
197} // namespace fuzzer
198
199#endif // LIBFUZZER_WINDOWS