• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "env-inl.h"
12 #include "util-inl.h"
13 #include "v8.h"
14 #include "libplatform/libplatform.h"
15 #include "aliased_buffer.h"
16 #include "fuzz_helper.h"
17 
18 using node::AliasedBufferBase;
19 
20 /* General set up */
21 using ArrayBufferUniquePtr = std::unique_ptr<node::ArrayBufferAllocator,
22   decltype(&node::FreeArrayBufferAllocator)>;
23 using TracingAgentUniquePtr = std::unique_ptr<node::tracing::Agent>;
24 using NodePlatformUniquePtr = std::unique_ptr<node::NodePlatform>;
25 
26 static TracingAgentUniquePtr tracing_agent;
27 static NodePlatformUniquePtr platform;
28 static uv_loop_t current_loop;
29 
LLVMFuzzerInitialize(int * argc,char *** argv)30 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
31   uv_os_unsetenv("NODE_OPTIONS");
32   std::vector<std::string> node_argv{ "fuzz_env" };
33   std::vector<std::string> exec_argv;
34   std::vector<std::string> errors;
35 
36   node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors);
37 
38   tracing_agent = std::make_unique<node::tracing::Agent>();
39   node::tracing::TraceEventHelper::SetAgent(tracing_agent.get());
40   node::tracing::TracingController* tracing_controller =
41     tracing_agent->GetTracingController();
42   CHECK_EQ(0, uv_loop_init(&current_loop));
43   static constexpr int kV8ThreadPoolSize = 4;
44   platform.reset(
45     new node::NodePlatform(kV8ThreadPoolSize, tracing_controller));
46   v8::V8::InitializePlatform(platform.get());
47   v8::V8::Initialize();
48   return 0;
49 }
50 
51 class FuzzerFixtureHelper {
52 public:
53   v8::Isolate* isolate_;
54   ArrayBufferUniquePtr allocator;
55 
FuzzerFixtureHelper()56   FuzzerFixtureHelper()
57     : allocator(ArrayBufferUniquePtr(node::CreateArrayBufferAllocator(),
58                                      &node::FreeArrayBufferAllocator)) {
59     isolate_ = NewIsolate(allocator.get(), &current_loop, platform.get());
60     CHECK_NOT_NULL(isolate_);
61     isolate_->Enter();
62   };
63 
Teardown()64   void Teardown() {
65     platform->DrainTasks(isolate_);
66     isolate_->Exit();
67     platform->UnregisterIsolate(isolate_);
68     isolate_->Dispose();
69     isolate_ = nullptr;
70   }
71 };
72 
EnvTest(v8::Isolate * isolate_,char * env_string)73 void EnvTest(v8::Isolate* isolate_, char* env_string) {
74   const v8::HandleScope handle_scope(isolate_);
75   Argv argv;
76 
77   node::EnvironmentFlags::Flags flags = node::EnvironmentFlags::kDefaultFlags;
78   auto isolate = handle_scope.GetIsolate();
79   v8::Local<v8::Context> context_ = node::NewContext(isolate);
80   context_->Enter();
81 
82   node::IsolateData* isolate_data_ = node::CreateIsolateData(isolate, &current_loop,
83                                                              platform.get());
84   std::vector<std::string> args(*argv, *argv + 1);
85   std::vector<std::string> exec_args(*argv, *argv + 1);
86   node::Environment* environment_ = node::CreateEnvironment(isolate_data_,
87                                           context_, args, exec_args, flags);
88   node::Environment* envi = environment_;
89   SetProcessExitHandler(envi, [&](node::Environment* env_, int exit_code) {
90     node::Stop(envi);
91   });
92   node::LoadEnvironment(envi, env_string);
93 
94   // Cleanup!
95   node::FreeEnvironment(environment_);
96   node::FreeIsolateData(isolate_data_);
97   context_->Exit();
98 }
99 
LLVMFuzzerTestOneInput(const uint8_t * data2,size_t size)100 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data2, size_t size) {
101   FuzzerFixtureHelper ffh;
102   std::string s(reinterpret_cast<const char*>(data2), size);
103   EnvTest(ffh.isolate_, (char*)s.c_str());
104   ffh.Teardown();
105   return 0;
106 }
107 
108