]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp
MFV r358616:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / compiler-rt / lib / fuzzer / FuzzerUtilWindows.cpp
1 //===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8 // Misc utils implementation for Windows.
9 //===----------------------------------------------------------------------===//
10 #include "FuzzerDefs.h"
11 #if LIBFUZZER_WINDOWS
12 #include "FuzzerCommand.h"
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 <stdio.h>
22 #include <sys/types.h>
23 #include <windows.h>
24
25 // This must be included after windows.h.
26 #include <psapi.h>
27
28 namespace fuzzer {
29
30 static const FuzzingOptions* HandlerOpt = nullptr;
31
32 static 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
67 BOOL 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
81 void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
82   Fuzzer::StaticAlarmCallback();
83 }
84
85 class TimerQ {
86   HANDLE TimerQueue;
87  public:
88   TimerQ() : TimerQueue(NULL) {}
89   ~TimerQ() {
90     if (TimerQueue)
91       DeleteTimerQueueEx(TimerQueue, NULL);
92   }
93   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     }
107   }
108 };
109
110 static TimerQ Timer;
111
112 static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
113
114 bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
115   return false;  // UNIMPLEMENTED
116 }
117
118 void 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
143 void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
144
145 unsigned long GetPid() { return GetCurrentProcessId(); }
146
147 size_t GetPeakRSSMb() {
148   PROCESS_MEMORY_COUNTERS info;
149   if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
150     return 0;
151   return info.PeakWorkingSetSize >> 20;
152 }
153
154 FILE *OpenProcessPipe(const char *Command, const char *Mode) {
155   return _popen(Command, Mode);
156 }
157
158 int ExecuteCommand(const Command &Cmd) {
159   std::string CmdLine = Cmd.toString();
160   return system(CmdLine.c_str());
161 }
162
163 const 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
184 std::string DisassembleCmd(const std::string &FileName) {
185   Vector<std::string> command_vector;
186   command_vector.push_back("dumpbin /summary > nul");
187   if (ExecuteCommand(Command(command_vector)) == 0)
188     return "dumpbin /disasm " + FileName;
189   Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n");
190   exit(1);
191 }
192
193 std::string SearchRegexCmd(const std::string &Regex) {
194   return "findstr /r \"" + Regex + "\"";
195 }
196
197 } // namespace fuzzer
198
199 #endif // LIBFUZZER_WINDOWS