Coverage Report

Created: 2025-08-28 09:57

/src/node/test/fuzzers/fuzz_sign_verify.cc
Line
Count
Source
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
#include <fuzzer/FuzzedDataProvider.h>
18
#include <cstdio>
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
32
122k
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
33
122k
  uv_os_unsetenv("NODE_OPTIONS");
34
122k
  std::vector<std::string> node_argv{ "fuzz_env" };
35
122k
  std::vector<std::string> exec_argv;
36
122k
  std::vector<std::string> errors;
37
38
122k
  node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors);
39
40
122k
  tracing_agent = std::make_unique<node::tracing::Agent>();
41
122k
  node::tracing::TraceEventHelper::SetAgent(tracing_agent.get());
42
122k
  node::tracing::TracingController* tracing_controller =
43
122k
    tracing_agent->GetTracingController();  
44
122k
  CHECK_EQ(0, uv_loop_init(&current_loop));
45
122k
  static constexpr int kV8ThreadPoolSize = 4;
46
122k
  platform.reset(
47
122k
    new node::NodePlatform(kV8ThreadPoolSize, tracing_controller));
48
122k
  v8::V8::InitializePlatform(platform.get());
49
122k
  cppgc::InitializeProcess(platform->GetPageAllocator());
50
122k
  v8::V8::Initialize();
51
122k
  return 0;
52
122k
}
53
54
class FuzzerFixtureHelper {
55
public:
56
  v8::Isolate* isolate_;
57
  ArrayBufferUniquePtr allocator;
58
59
  FuzzerFixtureHelper()
60
122k
    : allocator(ArrayBufferUniquePtr(node::CreateArrayBufferAllocator(),
61
122k
                                     &node::FreeArrayBufferAllocator)) {
62
122k
    isolate_ = NewIsolate(allocator.get(), &current_loop, platform.get());
63
122k
    CHECK_NOT_NULL(isolate_);
64
122k
    isolate_->Enter();
65
122k
  };
66
67
122k
  void Teardown() {
68
122k
    platform->DrainTasks(isolate_);
69
122k
    isolate_->Exit();
70
122k
    platform->UnregisterIsolate(isolate_);
71
122k
    isolate_->Dispose();
72
122k
    isolate_ = nullptr;
73
122k
  }
74
};
75
76
std::string W1 =
77
"var crypto = require(\"crypto\");\n"
78
"var eol = require('os').EOL;\n"
79
"\n"
80
"function RSASign(algorithm, privateKey, data) {\n"
81
"    const sign = crypto.createSign(algorithm);\n"
82
"    sign.update(data);\n"
83
"    var sig = sign.sign(privateKey, 'hex');\n"
84
"    return sig;\n"
85
"}\n"
86
"function RSAVerify(algorithm, publicKey, signature, data) {\n"
87
"    const verify = crypto.createVerify(algorithm);\n"
88
"    verify.update(data);\n"
89
"    var _ = verify.verify(publicKey, signature,'hex');\n"
90
"}\n"
91
"function getAlgorithm(index) {\n"
92
"    var allAlgorithms = crypto.getHashes();\n"
93
"    return allAlgorithms[index\%allAlgorithms.length];\n"
94
"}\n";
95
96
std::string W2 = "var pubStr = '";
97
//RANDOM
98
std::string W3 = "';\n"
99
  "var p = '";
100
//RANDOM
101
std::string W4 = "';\n"
102
  "var privateKey = '-----BEGIN PRIVATE KEY-----' + eol + p + eol + '-----END PRIVATE KEY-----';\n"
103
  "var publicKey= '-----BEGIN PUBLIC KEY-----' + eol + pubStr + eol + '-----END PUBLIC KEY-----';\n"
104
  "var dataToSign = \"";
105
//RANDOM
106
107
std::string W5 = "\";\n"
108
  "var algorithm = getAlgorithm(";
109
110
std::string W6 = ");\n"
111
  "var sig = RSASign(algorithm, privateKey, dataToSign);\n"
112
  "RSAVerify(algorithm, publicKey, sig, dataToSign);\n";
113
114
105k
void EnvTest(v8::Isolate* isolate_, char* env_string) {
115
105k
  const v8::HandleScope handle_scope(isolate_);
116
105k
  Argv argv;
117
118
105k
  node::EnvironmentFlags::Flags flags = node::EnvironmentFlags::kDefaultFlags;
119
105k
  auto isolate = handle_scope.GetIsolate();
120
105k
  v8::Local<v8::Context> context_ = node::NewContext(isolate);
121
105k
  context_->Enter();
122
123
105k
  node::IsolateData* isolate_data_ = node::CreateIsolateData(isolate, &current_loop,
124
105k
                                                             platform.get());
125
105k
  std::vector<std::string> args(*argv, *argv + 1);
126
105k
  std::vector<std::string> exec_args(*argv, *argv + 1);
127
105k
  node::Environment* environment_ = node::CreateEnvironment(isolate_data_,
128
105k
                                          context_, args, exec_args, flags);
129
105k
  node::Environment* envi = environment_;
130
105k
  SetProcessExitHandler(envi, [&](node::Environment* env_, int exit_code) {
131
2.80k
    node::Stop(envi);
132
2.80k
  });
133
105k
  node::LoadEnvironment(envi, env_string);
134
135
  // Cleanup!
136
105k
  node::FreeEnvironment(environment_);
137
105k
  node::FreeIsolateData(isolate_data_);
138
105k
  context_->Exit();
139
105k
}
140
141
11.2k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data2, size_t size) {
142
11.2k
  FuzzedDataProvider prov(data2, size);
143
11.2k
  std::string s1 = prov.ConsumeRandomLengthString();
144
11.2k
  std::string s2 = prov.ConsumeRandomLengthString();
145
11.2k
  std::string s3 = prov.ConsumeRandomLengthString();
146
11.2k
  int alg = prov.ConsumeIntegralInRange<int>(0, 999);
147
11.2k
  if (hasUnescapedSingleQuotes(s1)) {
148
91
    return 0;
149
91
  }
150
11.1k
  if (hasUnescapedSingleQuotes(s2)) {
151
55
    return 0;
152
55
  }
153
11.0k
  if (hasUnescapedDoubleQuotes(s3)) {
154
51
    return 0;
155
51
  }
156
11.0k
  std::stringstream stream;
157
11.0k
  stream << W1 << W2 << s1 << W3 << s2 << W4 << s3 << W5 << alg << W6 << std::endl;
158
11.0k
  std::string js_code = stream.str();
159
11.0k
  FuzzerFixtureHelper ffh;
160
11.0k
  EnvTest(ffh.isolate_, (char*)js_code.c_str());
161
11.0k
  ffh.Teardown();
162
11.0k
  return 0;
163
11.0k
}
164