1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 /*
7  * Interface definitions for the unified fuzzing interface
8  */
9 
10 #ifndef FuzzingInterface_h__
11 #define FuzzingInterface_h__
12 
13 #include <fstream>
14 
15 #ifdef LIBFUZZER
16 #  include "FuzzerExtFunctions.h"
17 #endif
18 
19 #include "FuzzerRegistry.h"
20 #include "mozilla/Assertions.h"
21 
22 #ifndef JS_STANDALONE
23 #  include "mozilla/Logging.h"
24 #endif
25 
26 namespace mozilla {
27 
28 #ifdef JS_STANDALONE
29 void fuzzing_log(const char* aFmt, ...);
30 #  define MOZ_LOG_EXPAND_ARGS(...) __VA_ARGS__
31 
32 #  define FUZZING_LOG(args) fuzzing_log(MOZ_LOG_EXPAND_ARGS args);
33 #else
34 extern LazyLogModule gFuzzingLog;
35 
36 #  define FUZZING_LOG(args) \
37     MOZ_LOG(mozilla::gFuzzingLog, mozilla::LogLevel::Verbose, args)
38 #endif  // JS_STANDALONE
39 
40 typedef int (*FuzzingTestFuncRaw)(const uint8_t*, size_t);
41 
42 #ifdef AFLFUZZ
43 
afl_interface_raw(const char * testFile,FuzzingTestFuncRaw testFunc)44 static int afl_interface_raw(const char* testFile,
45                              FuzzingTestFuncRaw testFunc) {
46   char* buf = NULL;
47 
48   while (__AFL_LOOP(1000)) {
49     std::ifstream is;
50     is.open(testFile, std::ios::binary);
51     is.seekg(0, std::ios::end);
52     int len = is.tellg();
53     is.seekg(0, std::ios::beg);
54     MOZ_RELEASE_ASSERT(len >= 0);
55     if (!len) {
56       is.close();
57       continue;
58     }
59     buf = (char*)realloc(buf, len);
60     MOZ_RELEASE_ASSERT(buf);
61     is.read(buf, len);
62     is.close();
63     testFunc((uint8_t*)buf, (size_t)len);
64   }
65 
66   free(buf);
67 
68   return 0;
69 }
70 
71 #  define MOZ_AFL_INTERFACE_COMMON()                                      \
72     char* testFilePtr = getenv("MOZ_FUZZ_TESTFILE");                      \
73     if (!testFilePtr) {                                                   \
74       fprintf(stderr,                                                     \
75               "Must specify testfile in MOZ_FUZZ_TESTFILE environment "   \
76               "variable.\n");                                             \
77       return 1;                                                           \
78     }                                                                     \
79     /* Make a copy of testFilePtr so the testing function can safely call \
80      * getenv                                                             \
81      */                                                                   \
82     std::string testFile(testFilePtr);
83 
84 #  define MOZ_AFL_INTERFACE_RAW(initFunc, testFunc, moduleName)          \
85     static int afl_fuzz_##moduleName(const uint8_t* data, size_t size) { \
86       MOZ_RELEASE_ASSERT(data == NULL && size == 0);                     \
87       MOZ_AFL_INTERFACE_COMMON();                                        \
88       return ::mozilla::afl_interface_raw(testFile.c_str(), testFunc);   \
89     }                                                                    \
90     static void __attribute__((constructor)) AFLRegister##moduleName() { \
91       ::mozilla::FuzzerRegistry::getInstance().registerModule(           \
92           #moduleName, initFunc, afl_fuzz_##moduleName);                 \
93     }
94 #else
95 #  define MOZ_AFL_INTERFACE_RAW(initFunc, testFunc, moduleName) /* Nothing */
96 #endif                                                          // AFLFUZZ
97 
98 #ifdef LIBFUZZER
99 #  define MOZ_LIBFUZZER_INTERFACE_RAW(initFunc, testFunc, moduleName)          \
100     static void __attribute__((constructor)) LibFuzzerRegister##moduleName() { \
101       ::mozilla::FuzzerRegistry::getInstance().registerModule(                 \
102           #moduleName, initFunc, testFunc);                                    \
103     }
104 #else
105 #  define MOZ_LIBFUZZER_INTERFACE_RAW(initFunc, testFunc, \
106                                       moduleName) /* Nothing */
107 #endif
108 
109 #define MOZ_FUZZING_INTERFACE_RAW(initFunc, testFunc, moduleName) \
110   MOZ_LIBFUZZER_INTERFACE_RAW(initFunc, testFunc, moduleName);    \
111   MOZ_AFL_INTERFACE_RAW(initFunc, testFunc, moduleName);
112 
113 }  // namespace mozilla
114 
115 #endif  // FuzzingInterface_h__
116