/src/node/test/fuzzers/fuzz_ParseGeneralReply.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * A fuzzer focused on the node::LoadEnvironment() function. |
3 | | * |
4 | | * Code here has been inspired by the cctest test case. |
5 | | */ |
6 | | |
7 | | #include <stdlib.h> |
8 | | #include "node.h" |
9 | | #include "node_platform.h" |
10 | | #include "node_internals.h" |
11 | | #include "ares_nameser.h" |
12 | | #include "crypto/crypto_bio.h" |
13 | | #include "crypto/crypto_context.h" |
14 | | #include "cares_wrap.h" |
15 | | #include "env-inl.h" |
16 | | #include "util-inl.h" |
17 | | #include "v8.h" |
18 | | #include "libplatform/libplatform.h" |
19 | | #include "aliased_buffer.h" |
20 | | #include "fuzz_helper.h" |
21 | | |
22 | | |
23 | | using node::AliasedBufferBase; |
24 | | using v8::Array; |
25 | | |
26 | | /*int ParseSrvReply( |
27 | | node::Environment* env, |
28 | | const unsigned char* buf, |
29 | | int len, |
30 | | v8::Local<Array> ret, |
31 | | bool need_type = false);*/ |
32 | | |
33 | | /* General set up */ |
34 | | using ArrayBufferUniquePtr = std::unique_ptr<node::ArrayBufferAllocator, |
35 | | decltype(&node::FreeArrayBufferAllocator)>; |
36 | | using TracingAgentUniquePtr = std::unique_ptr<node::tracing::Agent>; |
37 | | using NodePlatformUniquePtr = std::unique_ptr<node::NodePlatform>; |
38 | | |
39 | | static TracingAgentUniquePtr tracing_agent; |
40 | | static NodePlatformUniquePtr platform; |
41 | | static uv_loop_t current_loop; |
42 | | |
43 | 132k | extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { |
44 | 132k | uv_os_unsetenv("NODE_OPTIONS"); |
45 | 132k | std::vector<std::string> node_argv{ "fuzz_env" }; |
46 | 132k | std::vector<std::string> exec_argv; |
47 | 132k | std::vector<std::string> errors; |
48 | | |
49 | 132k | node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors); |
50 | | |
51 | 132k | tracing_agent = std::make_unique<node::tracing::Agent>(); |
52 | 132k | node::tracing::TraceEventHelper::SetAgent(tracing_agent.get()); |
53 | 132k | node::tracing::TracingController* tracing_controller = |
54 | 132k | tracing_agent->GetTracingController(); |
55 | 132k | CHECK_EQ(0, uv_loop_init(¤t_loop)); |
56 | 132k | static constexpr int kV8ThreadPoolSize = 4; |
57 | 132k | platform.reset( |
58 | 132k | new node::NodePlatform(kV8ThreadPoolSize, tracing_controller)); |
59 | 132k | v8::V8::InitializePlatform(platform.get()); |
60 | 132k | cppgc::InitializeProcess(platform->GetPageAllocator()); |
61 | 132k | v8::V8::Initialize(); |
62 | 132k | return 0; |
63 | 132k | } |
64 | | |
65 | | class FuzzerFixtureHelper { |
66 | | public: |
67 | | v8::Isolate* isolate_; |
68 | | ArrayBufferUniquePtr allocator; |
69 | | |
70 | | FuzzerFixtureHelper() |
71 | 134k | : allocator(ArrayBufferUniquePtr(node::CreateArrayBufferAllocator(), |
72 | 134k | &node::FreeArrayBufferAllocator)) { |
73 | 134k | isolate_ = NewIsolate(allocator.get(), ¤t_loop, platform.get()); |
74 | 134k | CHECK_NOT_NULL(isolate_); |
75 | 134k | isolate_->Enter(); |
76 | 134k | }; |
77 | | |
78 | 134k | void Teardown() { |
79 | 134k | platform->DrainTasks(isolate_); |
80 | 134k | isolate_->Exit(); |
81 | 134k | platform->UnregisterIsolate(isolate_); |
82 | 134k | isolate_->Dispose(); |
83 | 134k | isolate_ = nullptr; |
84 | 134k | } |
85 | | }; |
86 | | |
87 | 10.2k | void EnvTest(v8::Isolate* isolate_, char* env_string, size_t len) { |
88 | 10.2k | const v8::HandleScope handle_scope(isolate_); |
89 | 10.2k | Argv argv; |
90 | | |
91 | 10.2k | node::EnvironmentFlags::Flags flags = node::EnvironmentFlags::kDefaultFlags; |
92 | 10.2k | auto isolate = handle_scope.GetIsolate(); |
93 | 10.2k | v8::Local<v8::Context> context_ = node::NewContext(isolate); |
94 | 10.2k | context_->Enter(); |
95 | | |
96 | 10.2k | node::IsolateData* isolate_data_ = node::CreateIsolateData(isolate, ¤t_loop, |
97 | 10.2k | platform.get()); |
98 | 10.2k | std::vector<std::string> args(*argv, *argv + 1); |
99 | 10.2k | std::vector<std::string> exec_args(*argv, *argv + 1); |
100 | 10.2k | node::Environment* environment_ = node::CreateEnvironment(isolate_data_, |
101 | 10.2k | context_, args, exec_args, flags); |
102 | 10.2k | node::Environment* envi = environment_; |
103 | 10.2k | SetProcessExitHandler(envi, [&](node::Environment* env_, int exit_code) { |
104 | 0 | node::Stop(envi); |
105 | 0 | }); |
106 | 10.2k | node::LoadEnvironment(envi, ""); |
107 | 10.2k | unsigned char* p = reinterpret_cast<unsigned char*>(env_string); |
108 | 10.2k | int type = node::cares_wrap::ns_t_cname_or_a; |
109 | | |
110 | 10.2k | v8::Local<v8::Array> srv_records = Array::New(envi->isolate()); |
111 | 10.2k | int status = node::cares_wrap::FuzzParseGeneralReply(envi, p, (int)len, &type, srv_records); |
112 | | |
113 | | // Cleanup! |
114 | 10.2k | node::FreeEnvironment(environment_); |
115 | 10.2k | node::FreeIsolateData(isolate_data_); |
116 | 10.2k | context_->Exit(); |
117 | 10.2k | } |
118 | | |
119 | 36.0k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data2, size_t size) { |
120 | 36.0k | FuzzerFixtureHelper ffh; |
121 | 36.0k | std::string s(reinterpret_cast<const char*>(data2), size); |
122 | 36.0k | EnvTest(ffh.isolate_, (char*)s.c_str(), size); |
123 | 36.0k | ffh.Teardown(); |
124 | 36.0k | return 0; |
125 | 36.0k | } |
126 | | |