| 
 | 1 | +/*  | 
 | 2 | + * A fuzzer focused on C string -> Javascript String.  | 
 | 3 | +*/  | 
 | 4 | + | 
 | 5 | +#include <stdlib.h>  | 
 | 6 | +#include "js_native_api.h"  | 
 | 7 | +#include "js_native_api_v8.h"  | 
 | 8 | +#include "node.h"  | 
 | 9 | +#include "node_platform.h"  | 
 | 10 | +#include "node_internals.h"  | 
 | 11 | +#include "node_api_internals.h"  | 
 | 12 | +#include "node_url.h"  | 
 | 13 | +#include "env-inl.h"  | 
 | 14 | +#include "util-inl.h"  | 
 | 15 | +#include "v8.h"  | 
 | 16 | +#include "libplatform/libplatform.h"  | 
 | 17 | +#include "aliased_buffer.h"  | 
 | 18 | +#include "fuzz_helper.h"  | 
 | 19 | + | 
 | 20 | +using node::AliasedBufferBase;  | 
 | 21 | + | 
 | 22 | +/* General set up */  | 
 | 23 | +using ArrayBufferUniquePtr = std::unique_ptr<node::ArrayBufferAllocator,  | 
 | 24 | +  decltype(&node::FreeArrayBufferAllocator)>;  | 
 | 25 | +using TracingAgentUniquePtr = std::unique_ptr<node::tracing::Agent>;  | 
 | 26 | +using NodePlatformUniquePtr = std::unique_ptr<node::NodePlatform>;  | 
 | 27 | + | 
 | 28 | +static TracingAgentUniquePtr tracing_agent;  | 
 | 29 | +static NodePlatformUniquePtr platform;  | 
 | 30 | +static uv_loop_t current_loop;  | 
 | 31 | +static napi_env addon_env;  | 
 | 32 | + | 
 | 33 | +inline napi_env NewEnv(v8::Local<v8::Context> context,  | 
 | 34 | +                       const std::string& module_filename,  | 
 | 35 | +                       int32_t module_api_version) ;  | 
 | 36 | + | 
 | 37 | +extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {  | 
 | 38 | +  uv_os_unsetenv("NODE_OPTIONS");  | 
 | 39 | +  std::vector<std::string> node_argv{ "fuzz_string_conversion" };  | 
 | 40 | +  std::vector<std::string> exec_argv;  | 
 | 41 | +  std::vector<std::string> errors;  | 
 | 42 | + | 
 | 43 | +  node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors);  | 
 | 44 | + | 
 | 45 | +  tracing_agent = std::make_unique<node::tracing::Agent>();  | 
 | 46 | +  node::tracing::TraceEventHelper::SetAgent(tracing_agent.get());  | 
 | 47 | +  node::tracing::TracingController* tracing_controller =  | 
 | 48 | +    tracing_agent->GetTracingController();    | 
 | 49 | +  CHECK_EQ(0, uv_loop_init(¤t_loop));  | 
 | 50 | +  static constexpr int kV8ThreadPoolSize = 4;  | 
 | 51 | +  platform.reset(  | 
 | 52 | +    new node::NodePlatform(kV8ThreadPoolSize, tracing_controller));  | 
 | 53 | +  v8::V8::InitializePlatform(platform.get());  | 
 | 54 | +  cppgc::InitializeProcess(platform->GetPageAllocator());  | 
 | 55 | +  v8::V8::Initialize();  | 
 | 56 | +  return 0;  | 
 | 57 | +}  | 
 | 58 | + | 
 | 59 | +class FuzzerFixtureHelper {  | 
 | 60 | +public:  | 
 | 61 | +  v8::Isolate* isolate_;  | 
 | 62 | +  ArrayBufferUniquePtr allocator;  | 
 | 63 | + | 
 | 64 | +  FuzzerFixtureHelper()  | 
 | 65 | +    : allocator(ArrayBufferUniquePtr(node::CreateArrayBufferAllocator(),  | 
 | 66 | +                                     &node::FreeArrayBufferAllocator)) {  | 
 | 67 | +    isolate_ = NewIsolate(allocator.get(), ¤t_loop, platform.get());  | 
 | 68 | +    CHECK_NOT_NULL(isolate_);  | 
 | 69 | +    isolate_->Enter();  | 
 | 70 | +  };  | 
 | 71 | + | 
 | 72 | +  void Teardown() {  | 
 | 73 | +    platform->DrainTasks(isolate_);  | 
 | 74 | +    isolate_->Exit();  | 
 | 75 | +    platform->UnregisterIsolate(isolate_);  | 
 | 76 | +    isolate_->Dispose();  | 
 | 77 | +    isolate_ = nullptr;  | 
 | 78 | +  }  | 
 | 79 | +};  | 
 | 80 | + | 
 | 81 | +void EnvTest(v8::Isolate* isolate_, char* env_string, size_t size) {  | 
 | 82 | +  const v8::HandleScope handle_scope(isolate_);  | 
 | 83 | +  Argv argv;  | 
 | 84 | + | 
 | 85 | +  node::EnvironmentFlags::Flags flags = node::EnvironmentFlags::kDefaultFlags;  | 
 | 86 | +  auto isolate = handle_scope.GetIsolate();  | 
 | 87 | +  v8::Local<v8::Context> context_ = node::NewContext(isolate);  | 
 | 88 | +  context_->Enter();  | 
 | 89 | + | 
 | 90 | +  node::IsolateData* isolate_data_ = node::CreateIsolateData(isolate, ¤t_loop,  | 
 | 91 | +                                                             platform.get());  | 
 | 92 | +  std::vector<std::string> args(*argv, *argv + 1);  | 
 | 93 | +  std::vector<std::string> exec_args(*argv, *argv + 1);  | 
 | 94 | +  node::Environment* environment_ = node::CreateEnvironment(isolate_data_,  | 
 | 95 | +                                          context_, args, exec_args, flags);  | 
 | 96 | +  node::Environment* envi = environment_;  | 
 | 97 | +  SetProcessExitHandler(envi, [&](node::Environment* env_, int exit_code) {  | 
 | 98 | +    node::Stop(envi);  | 
 | 99 | +  });  | 
 | 100 | +  node::LoadEnvironment(envi, "");  | 
 | 101 | + | 
 | 102 | + | 
 | 103 | +  napi_addon_register_func init = [](napi_env env, napi_value exports) {  | 
 | 104 | +    addon_env = env;  | 
 | 105 | +    return exports;  | 
 | 106 | +  };  | 
 | 107 | +  v8::Local<v8::Object> module_obj = v8::Object::New(isolate);  | 
 | 108 | +  v8::Local<v8::Object> exports_obj = v8::Object::New(isolate);  | 
 | 109 | +  napi_module_register_by_symbol(  | 
 | 110 | +      exports_obj, module_obj, context_, init, NAPI_VERSION);  | 
 | 111 | +  size_t copied1, copied2;  | 
 | 112 | +  napi_value output1, output2;  | 
 | 113 | +  char *buf1 = (char *)malloc(size);  | 
 | 114 | +  char *buf2 = (char *)malloc(size);  | 
 | 115 | +  napi_create_string_utf8(addon_env, env_string, size, &output1);  | 
 | 116 | +  napi_get_value_string_utf8(addon_env, output1, buf1, size, &copied1);  | 
 | 117 | +  napi_create_string_latin1(addon_env, env_string, size, &output2);  | 
 | 118 | +  napi_get_value_string_latin1(addon_env, output2, buf2, size, &copied2);  | 
 | 119 | +  free(buf1);  | 
 | 120 | +  free(buf2);  | 
 | 121 | + | 
 | 122 | +  // Cleanup!  | 
 | 123 | +  node::FreeEnvironment(environment_);  | 
 | 124 | +  node::FreeIsolateData(isolate_data_);  | 
 | 125 | +  context_->Exit();  | 
 | 126 | +}  | 
 | 127 | + | 
 | 128 | +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data2, size_t size) {  | 
 | 129 | +  FuzzerFixtureHelper ffh;  | 
 | 130 | +  std::string s(reinterpret_cast<const char*>(data2), size);  | 
 | 131 | +  EnvTest(ffh.isolate_, (char*)s.c_str(), size);  | 
 | 132 | +  ffh.Teardown();  | 
 | 133 | +  return 0;  | 
 | 134 | +}  | 
 | 135 | + | 
0 commit comments