1c5f01b2fSopenharmony_ci//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//
2c5f01b2fSopenharmony_ci//
3c5f01b2fSopenharmony_ci//                     The LLVM Compiler Infrastructure
4c5f01b2fSopenharmony_ci//
5c5f01b2fSopenharmony_ci// This file is distributed under the University of Illinois Open Source
6c5f01b2fSopenharmony_ci// License. See LICENSE.TXT for details.
7c5f01b2fSopenharmony_ci//
8c5f01b2fSopenharmony_ci//===----------------------------------------------------------------------===//
9c5f01b2fSopenharmony_ci// Misc utils implementation for Windows.
10c5f01b2fSopenharmony_ci//===----------------------------------------------------------------------===//
11c5f01b2fSopenharmony_ci#include "FuzzerDefs.h"
12c5f01b2fSopenharmony_ci#if LIBFUZZER_WINDOWS
13c5f01b2fSopenharmony_ci#include "FuzzerIO.h"
14c5f01b2fSopenharmony_ci#include "FuzzerInternal.h"
15c5f01b2fSopenharmony_ci#include <cassert>
16c5f01b2fSopenharmony_ci#include <chrono>
17c5f01b2fSopenharmony_ci#include <cstring>
18c5f01b2fSopenharmony_ci#include <errno.h>
19c5f01b2fSopenharmony_ci#include <iomanip>
20c5f01b2fSopenharmony_ci#include <signal.h>
21c5f01b2fSopenharmony_ci#include <sstream>
22c5f01b2fSopenharmony_ci#include <stdio.h>
23c5f01b2fSopenharmony_ci#include <sys/types.h>
24c5f01b2fSopenharmony_ci#include <windows.h>
25c5f01b2fSopenharmony_ci#include <Psapi.h>
26c5f01b2fSopenharmony_ci
27c5f01b2fSopenharmony_cinamespace fuzzer {
28c5f01b2fSopenharmony_ci
29c5f01b2fSopenharmony_cistatic const FuzzingOptions* HandlerOpt = nullptr;
30c5f01b2fSopenharmony_ci
31c5f01b2fSopenharmony_ciLONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
32c5f01b2fSopenharmony_ci  switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
33c5f01b2fSopenharmony_ci    case EXCEPTION_ACCESS_VIOLATION:
34c5f01b2fSopenharmony_ci    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
35c5f01b2fSopenharmony_ci    case EXCEPTION_STACK_OVERFLOW:
36c5f01b2fSopenharmony_ci      if (HandlerOpt->HandleSegv)
37c5f01b2fSopenharmony_ci        Fuzzer::StaticCrashSignalCallback();
38c5f01b2fSopenharmony_ci      break;
39c5f01b2fSopenharmony_ci    case EXCEPTION_DATATYPE_MISALIGNMENT:
40c5f01b2fSopenharmony_ci    case EXCEPTION_IN_PAGE_ERROR:
41c5f01b2fSopenharmony_ci      if (HandlerOpt->HandleBus)
42c5f01b2fSopenharmony_ci        Fuzzer::StaticCrashSignalCallback();
43c5f01b2fSopenharmony_ci      break;
44c5f01b2fSopenharmony_ci    case EXCEPTION_ILLEGAL_INSTRUCTION:
45c5f01b2fSopenharmony_ci    case EXCEPTION_PRIV_INSTRUCTION:
46c5f01b2fSopenharmony_ci      if (HandlerOpt->HandleIll)
47c5f01b2fSopenharmony_ci        Fuzzer::StaticCrashSignalCallback();
48c5f01b2fSopenharmony_ci      break;
49c5f01b2fSopenharmony_ci    case EXCEPTION_FLT_DENORMAL_OPERAND:
50c5f01b2fSopenharmony_ci    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
51c5f01b2fSopenharmony_ci    case EXCEPTION_FLT_INEXACT_RESULT:
52c5f01b2fSopenharmony_ci    case EXCEPTION_FLT_INVALID_OPERATION:
53c5f01b2fSopenharmony_ci    case EXCEPTION_FLT_OVERFLOW:
54c5f01b2fSopenharmony_ci    case EXCEPTION_FLT_STACK_CHECK:
55c5f01b2fSopenharmony_ci    case EXCEPTION_FLT_UNDERFLOW:
56c5f01b2fSopenharmony_ci    case EXCEPTION_INT_DIVIDE_BY_ZERO:
57c5f01b2fSopenharmony_ci    case EXCEPTION_INT_OVERFLOW:
58c5f01b2fSopenharmony_ci      if (HandlerOpt->HandleFpe)
59c5f01b2fSopenharmony_ci        Fuzzer::StaticCrashSignalCallback();
60c5f01b2fSopenharmony_ci      break;
61c5f01b2fSopenharmony_ci  }
62c5f01b2fSopenharmony_ci  return EXCEPTION_CONTINUE_SEARCH;
63c5f01b2fSopenharmony_ci}
64c5f01b2fSopenharmony_ci
65c5f01b2fSopenharmony_ciBOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
66c5f01b2fSopenharmony_ci  switch (dwCtrlType) {
67c5f01b2fSopenharmony_ci    case CTRL_C_EVENT:
68c5f01b2fSopenharmony_ci      if (HandlerOpt->HandleInt)
69c5f01b2fSopenharmony_ci        Fuzzer::StaticInterruptCallback();
70c5f01b2fSopenharmony_ci      return TRUE;
71c5f01b2fSopenharmony_ci    case CTRL_BREAK_EVENT:
72c5f01b2fSopenharmony_ci      if (HandlerOpt->HandleTerm)
73c5f01b2fSopenharmony_ci        Fuzzer::StaticInterruptCallback();
74c5f01b2fSopenharmony_ci      return TRUE;
75c5f01b2fSopenharmony_ci  }
76c5f01b2fSopenharmony_ci  return FALSE;
77c5f01b2fSopenharmony_ci}
78c5f01b2fSopenharmony_ci
79c5f01b2fSopenharmony_civoid CALLBACK AlarmHandler(PVOID, BOOLEAN) {
80c5f01b2fSopenharmony_ci  Fuzzer::StaticAlarmCallback();
81c5f01b2fSopenharmony_ci}
82c5f01b2fSopenharmony_ci
83c5f01b2fSopenharmony_ciclass TimerQ {
84c5f01b2fSopenharmony_ci  HANDLE TimerQueue;
85c5f01b2fSopenharmony_ci public:
86c5f01b2fSopenharmony_ci  TimerQ() : TimerQueue(NULL) {};
87c5f01b2fSopenharmony_ci  ~TimerQ() {
88c5f01b2fSopenharmony_ci    if (TimerQueue)
89c5f01b2fSopenharmony_ci      DeleteTimerQueueEx(TimerQueue, NULL);
90c5f01b2fSopenharmony_ci  };
91c5f01b2fSopenharmony_ci  void SetTimer(int Seconds) {
92c5f01b2fSopenharmony_ci    if (!TimerQueue) {
93c5f01b2fSopenharmony_ci      TimerQueue = CreateTimerQueue();
94c5f01b2fSopenharmony_ci      if (!TimerQueue) {
95c5f01b2fSopenharmony_ci        Printf("libFuzzer: CreateTimerQueue failed.\n");
96c5f01b2fSopenharmony_ci        exit(1);
97c5f01b2fSopenharmony_ci      }
98c5f01b2fSopenharmony_ci    }
99c5f01b2fSopenharmony_ci    HANDLE Timer;
100c5f01b2fSopenharmony_ci    if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
101c5f01b2fSopenharmony_ci        Seconds*1000, Seconds*1000, 0)) {
102c5f01b2fSopenharmony_ci      Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
103c5f01b2fSopenharmony_ci      exit(1);
104c5f01b2fSopenharmony_ci    }
105c5f01b2fSopenharmony_ci  };
106c5f01b2fSopenharmony_ci};
107c5f01b2fSopenharmony_ci
108c5f01b2fSopenharmony_cistatic TimerQ Timer;
109c5f01b2fSopenharmony_ci
110c5f01b2fSopenharmony_cistatic void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
111c5f01b2fSopenharmony_ci
112c5f01b2fSopenharmony_civoid SetSignalHandler(const FuzzingOptions& Options) {
113c5f01b2fSopenharmony_ci  HandlerOpt = &Options;
114c5f01b2fSopenharmony_ci
115c5f01b2fSopenharmony_ci  if (Options.UnitTimeoutSec > 0)
116c5f01b2fSopenharmony_ci    Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
117c5f01b2fSopenharmony_ci
118c5f01b2fSopenharmony_ci  if (Options.HandleInt || Options.HandleTerm)
119c5f01b2fSopenharmony_ci    if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
120c5f01b2fSopenharmony_ci      DWORD LastError = GetLastError();
121c5f01b2fSopenharmony_ci      Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
122c5f01b2fSopenharmony_ci        LastError);
123c5f01b2fSopenharmony_ci      exit(1);
124c5f01b2fSopenharmony_ci    }
125c5f01b2fSopenharmony_ci
126c5f01b2fSopenharmony_ci  if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
127c5f01b2fSopenharmony_ci      Options.HandleFpe)
128c5f01b2fSopenharmony_ci    if (!AddVectoredExceptionHandler(1, ExceptionHandler)) {
129c5f01b2fSopenharmony_ci      Printf("libFuzzer: AddVectoredExceptionHandler failed.\n");
130c5f01b2fSopenharmony_ci      exit(1);
131c5f01b2fSopenharmony_ci    }
132c5f01b2fSopenharmony_ci
133c5f01b2fSopenharmony_ci  if (Options.HandleAbrt)
134c5f01b2fSopenharmony_ci    if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
135c5f01b2fSopenharmony_ci      Printf("libFuzzer: signal failed with %d\n", errno);
136c5f01b2fSopenharmony_ci      exit(1);
137c5f01b2fSopenharmony_ci    }
138c5f01b2fSopenharmony_ci}
139c5f01b2fSopenharmony_ci
140c5f01b2fSopenharmony_civoid SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
141c5f01b2fSopenharmony_ci
142c5f01b2fSopenharmony_ciunsigned long GetPid() { return GetCurrentProcessId(); }
143c5f01b2fSopenharmony_ci
144c5f01b2fSopenharmony_cisize_t GetPeakRSSMb() {
145c5f01b2fSopenharmony_ci  PROCESS_MEMORY_COUNTERS info;
146c5f01b2fSopenharmony_ci  if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
147c5f01b2fSopenharmony_ci    return 0;
148c5f01b2fSopenharmony_ci  return info.PeakWorkingSetSize >> 20;
149c5f01b2fSopenharmony_ci}
150c5f01b2fSopenharmony_ci
151c5f01b2fSopenharmony_ciFILE *OpenProcessPipe(const char *Command, const char *Mode) {
152c5f01b2fSopenharmony_ci  return _popen(Command, Mode);
153c5f01b2fSopenharmony_ci}
154c5f01b2fSopenharmony_ci
155c5f01b2fSopenharmony_ciint ExecuteCommand(const std::string &Command) {
156c5f01b2fSopenharmony_ci  return system(Command.c_str());
157c5f01b2fSopenharmony_ci}
158c5f01b2fSopenharmony_ci
159c5f01b2fSopenharmony_ciconst void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
160c5f01b2fSopenharmony_ci                         size_t PattLen) {
161c5f01b2fSopenharmony_ci  // TODO: make this implementation more efficient.
162c5f01b2fSopenharmony_ci  const char *Cdata = (const char *)Data;
163c5f01b2fSopenharmony_ci  const char *Cpatt = (const char *)Patt;
164c5f01b2fSopenharmony_ci
165c5f01b2fSopenharmony_ci  if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
166c5f01b2fSopenharmony_ci    return NULL;
167c5f01b2fSopenharmony_ci
168c5f01b2fSopenharmony_ci  if (PattLen == 1)
169c5f01b2fSopenharmony_ci    return memchr(Data, *Cpatt, DataLen);
170c5f01b2fSopenharmony_ci
171c5f01b2fSopenharmony_ci  const char *End = Cdata + DataLen - PattLen + 1;
172c5f01b2fSopenharmony_ci
173c5f01b2fSopenharmony_ci  for (const char *It = Cdata; It < End; ++It)
174c5f01b2fSopenharmony_ci    if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
175c5f01b2fSopenharmony_ci      return It;
176c5f01b2fSopenharmony_ci
177c5f01b2fSopenharmony_ci  return NULL;
178c5f01b2fSopenharmony_ci}
179c5f01b2fSopenharmony_ci
180c5f01b2fSopenharmony_ci} // namespace fuzzer
181c5f01b2fSopenharmony_ci
182c5f01b2fSopenharmony_ci#endif // LIBFUZZER_WINDOWS
183