Bug Summary

File:out/../src/node_process_methods.cc
Warning:line 72, column 6
Dereference of null pointer (loaded from variable 'd')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name node_process_methods.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D NODE_ARCH="x64" -D NODE_PLATFORM="linux" -D NODE_WANT_INTERNALS=1 -D V8_DEPRECATION_WARNINGS=1 -D NODE_OPENSSL_SYSTEM_CERT_PATH="" -D NODE_USE_NODE_CODE_CACHE=1 -D HAVE_INSPECTOR=1 -D NODE_ENABLE_LARGE_CODE_PAGES=1 -D __POSIX__ -D NODE_USE_V8_PLATFORM=1 -D NODE_HAVE_I18N_SUPPORT=1 -D HAVE_OPENSSL=1 -D OPENSSL_API_COMPAT=0x10100000L -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -D _LARGEFILE_SOURCE -D _FILE_OFFSET_BITS=64 -D _POSIX_C_SOURCE=200112 -D NGHTTP2_STATICLIB -D NDEBUG -D OPENSSL_USE_NODELETE -D L_ENDIAN -D OPENSSL_BUILDING_OPENSSL -D AES_ASM -D BSAES_ASM -D CMLL_ASM -D ECP_NISTZ256_ASM -D GHASH_ASM -D KECCAK1600_ASM -D MD5_ASM -D OPENSSL_BN_ASM_GF2m -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_CPUID_OBJ -D OPENSSL_IA32_SSE2 -D PADLOCK_ASM -D POLY1305_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D VPAES_ASM -D WHIRLPOOL_ASM -D X25519_ASM -D OPENSSL_PIC -D NGTCP2_STATICLIB -D NGHTTP3_STATICLIB -I ../src -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/src -I ../deps/googletest/include -I ../deps/histogram/src -I ../deps/uvwasi/include -I ../deps/v8/include -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/zlib -I ../deps/llhttp/include -I ../deps/cares/include -I ../deps/uv/include -I ../deps/nghttp2/lib/includes -I ../deps/brotli/c/include -I ../deps/openssl/openssl/include -I ../deps/openssl/openssl/crypto/include -I ../deps/openssl/config/archs/linux-x86_64/asm/include -I ../deps/openssl/config/archs/linux-x86_64/asm -I ../deps/ngtcp2 -I ../deps/ngtcp2/ngtcp2/lib/includes -I ../deps/ngtcp2/ngtcp2/crypto/includes -I ../deps/ngtcp2/nghttp3/lib/includes -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-unused-parameter -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../src/node_process_methods.cc
1#include "async_wrap-inl.h"
2#include "base_object-inl.h"
3#include "debug_utils-inl.h"
4#include "env-inl.h"
5#include "memory_tracker-inl.h"
6#include "node.h"
7#include "node_errors.h"
8#include "node_external_reference.h"
9#include "node_internals.h"
10#include "node_process-inl.h"
11#include "util-inl.h"
12#include "uv.h"
13#include "v8-fast-api-calls.h"
14#include "v8.h"
15
16#include <vector>
17
18#if HAVE_INSPECTOR1
19#include "inspector_io.h"
20#endif
21
22#include <climits> // PATH_MAX
23#include <cstdio>
24
25#if defined(_MSC_VER)
26#include <direct.h>
27#include <io.h>
28#define umask _umask
29typedef int mode_t;
30#else
31#include <pthread.h>
32#include <sys/resource.h> // getrlimit, setrlimit
33#include <termios.h> // tcgetattr, tcsetattr
34#endif
35
36namespace node {
37
38using v8::Array;
39using v8::ArrayBuffer;
40using v8::CFunction;
41using v8::Context;
42using v8::Float64Array;
43using v8::FunctionCallbackInfo;
44using v8::HeapStatistics;
45using v8::Integer;
46using v8::Isolate;
47using v8::Local;
48using v8::NewStringType;
49using v8::Number;
50using v8::Object;
51using v8::String;
52using v8::Uint32;
53using v8::Value;
54
55namespace per_process {
56Mutex umask_mutex;
57} // namespace per_process
58
59// Microseconds in a second, as a float, used in CPUUsage() below
60#define MICROS_PER_SEC1e6 1e6
61// used in Hrtime() and Uptime() below
62#define NANOS_PER_SEC1000000000 1000000000
63
64static void Abort(const FunctionCallbackInfo<Value>& args) {
65 Abort();
66}
67
68// For internal testing only, not exposed to userland.
69static void CauseSegfault(const FunctionCallbackInfo<Value>& args) {
70 // This should crash hard all platforms.
71 volatile void** d = static_cast<volatile void**>(nullptr);
1
'd' initialized to a null pointer value
72 *d = nullptr;
2
Dereference of null pointer (loaded from variable 'd')
73}
74
75static void Chdir(const FunctionCallbackInfo<Value>& args) {
76 Environment* env = Environment::GetCurrent(args);
77 CHECK(env->owns_process_state())do { if (__builtin_expect(!!(!(env->owns_process_state()))
, 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "77", "env->owns_process_state()", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
78
79 CHECK_EQ(args.Length(), 1)do { if (__builtin_expect(!!(!((args.Length()) == (1))), 0)) {
do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "79", "(args.Length()) == (1)", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
80 CHECK(args[0]->IsString())do { if (__builtin_expect(!!(!(args[0]->IsString())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "80", "args[0]->IsString()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
81 Utf8Value path(env->isolate(), args[0]);
82 int err = uv_chdir(*path);
83 if (err) {
84 // Also include the original working directory, since that will usually
85 // be helpful information when debugging a `chdir()` failure.
86 char buf[PATH_MAX_BYTES(4096)];
87 size_t cwd_len = sizeof(buf);
88 uv_cwd(buf, &cwd_len);
89 return env->ThrowUVException(err, "chdir", nullptr, buf, *path);
90 }
91}
92
93inline Local<ArrayBuffer> get_fields_array_buffer(
94 const FunctionCallbackInfo<Value>& args,
95 size_t index,
96 size_t array_length) {
97 CHECK(args[index]->IsFloat64Array())do { if (__builtin_expect(!!(!(args[index]->IsFloat64Array
())), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "97", "args[index]->IsFloat64Array()", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
98 Local<Float64Array> arr = args[index].As<Float64Array>();
99 CHECK_EQ(arr->Length(), array_length)do { if (__builtin_expect(!!(!((arr->Length()) == (array_length
))), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "99", "(arr->Length()) == (array_length)", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
100 return arr->Buffer();
101}
102
103// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
104// to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
105// which are uv_timeval_t structs (long tv_sec, long tv_usec).
106// Returns those values as Float64 microseconds in the elements of the array
107// passed to the function.
108static void CPUUsage(const FunctionCallbackInfo<Value>& args) {
109 Environment* env = Environment::GetCurrent(args);
110 uv_rusage_t rusage;
111
112 // Call libuv to get the values we'll return.
113 int err = uv_getrusage(&rusage);
114 if (err)
115 return env->ThrowUVException(err, "uv_getrusage");
116
117 // Get the double array pointer from the Float64Array argument.
118 Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 2);
119 double* fields = static_cast<double*>(ab->GetBackingStore()->Data());
120
121 // Set the Float64Array elements to be user / system values in microseconds.
122 fields[0] = MICROS_PER_SEC1e6 * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
123 fields[1] = MICROS_PER_SEC1e6 * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
124}
125
126static void Cwd(const FunctionCallbackInfo<Value>& args) {
127 Environment* env = Environment::GetCurrent(args);
128 CHECK(env->has_run_bootstrapping_code())do { if (__builtin_expect(!!(!(env->has_run_bootstrapping_code
())), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "128", "env->has_run_bootstrapping_code()", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
129 char buf[PATH_MAX_BYTES(4096)];
130 size_t cwd_len = sizeof(buf);
131 int err = uv_cwd(buf, &cwd_len);
132 if (err)
133 return env->ThrowUVException(err, "uv_cwd");
134
135 Local<String> cwd = String::NewFromUtf8(env->isolate(),
136 buf,
137 NewStringType::kNormal,
138 cwd_len).ToLocalChecked();
139 args.GetReturnValue().Set(cwd);
140}
141
142static void Kill(const FunctionCallbackInfo<Value>& args) {
143 Environment* env = Environment::GetCurrent(args);
144 Local<Context> context = env->context();
145
146 if (args.Length() < 2) {
147 THROW_ERR_MISSING_ARGS(env, "Bad argument.");
148 }
149
150 int pid;
151 if (!args[0]->Int32Value(context).To(&pid)) return;
152 int sig;
153 if (!args[1]->Int32Value(context).To(&sig)) return;
154
155 uv_pid_t own_pid = uv_os_getpid();
156 if (sig > 0 &&
157 (pid == 0 || pid == -1 || pid == own_pid || pid == -own_pid) &&
158 !HasSignalJSHandler(sig)) {
159 // This is most likely going to terminate this process.
160 // It's not an exact method but it might be close enough.
161 RunAtExit(env);
162 }
163
164 int err = uv_kill(pid, sig);
165 args.GetReturnValue().Set(err);
166}
167
168static void Rss(const FunctionCallbackInfo<Value>& args) {
169 Environment* env = Environment::GetCurrent(args);
170
171 size_t rss;
172 int err = uv_resident_set_memory(&rss);
173 if (err)
174 return env->ThrowUVException(err, "uv_resident_set_memory");
175
176 args.GetReturnValue().Set(static_cast<double>(rss));
177}
178
179static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
180 Environment* env = Environment::GetCurrent(args);
181
182 Isolate* isolate = env->isolate();
183 // V8 memory usage
184 HeapStatistics v8_heap_stats;
185 isolate->GetHeapStatistics(&v8_heap_stats);
186
187 NodeArrayBufferAllocator* array_buffer_allocator =
188 env->isolate_data()->node_allocator();
189
190 // Get the double array pointer from the Float64Array argument.
191 Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 5);
192 double* fields = static_cast<double*>(ab->GetBackingStore()->Data());
193
194 size_t rss;
195 int err = uv_resident_set_memory(&rss);
196 if (err)
197 return env->ThrowUVException(err, "uv_resident_set_memory");
198
199 fields[0] = static_cast<double>(rss);
200 fields[1] = static_cast<double>(v8_heap_stats.total_heap_size());
201 fields[2] = static_cast<double>(v8_heap_stats.used_heap_size());
202 fields[3] = static_cast<double>(v8_heap_stats.external_memory());
203 fields[4] =
204 array_buffer_allocator == nullptr
205 ? 0
206 : static_cast<double>(array_buffer_allocator->total_mem_usage());
207}
208
209void RawDebug(const FunctionCallbackInfo<Value>& args) {
210 CHECK(args.Length() == 1 && args[0]->IsString() &&do { if (__builtin_expect(!!(!(args.Length() == 1 && args
[0]->IsString() && "must be called with a single string"
)), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "211", "args.Length() == 1 && args[0]->IsString() && \"must be called with a single string\""
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
211 "must be called with a single string")do { if (__builtin_expect(!!(!(args.Length() == 1 && args
[0]->IsString() && "must be called with a single string"
)), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "211", "args.Length() == 1 && args[0]->IsString() && \"must be called with a single string\""
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
212 Utf8Value message(args.GetIsolate(), args[0]);
213 FPrintF(stderrstderr, "%s\n", message);
214 fflush(stderrstderr);
215}
216
217static void Umask(const FunctionCallbackInfo<Value>& args) {
218 Environment* env = Environment::GetCurrent(args);
219 CHECK(env->has_run_bootstrapping_code())do { if (__builtin_expect(!!(!(env->has_run_bootstrapping_code
())), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "219", "env->has_run_bootstrapping_code()", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
220 CHECK_EQ(args.Length(), 1)do { if (__builtin_expect(!!(!((args.Length()) == (1))), 0)) {
do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "220", "(args.Length()) == (1)", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
221 CHECK(args[0]->IsUndefined() || args[0]->IsUint32())do { if (__builtin_expect(!!(!(args[0]->IsUndefined() || args
[0]->IsUint32())), 0)) { do { static const node::AssertionInfo
args = { "../src/node_process_methods.cc" ":" "221", "args[0]->IsUndefined() || args[0]->IsUint32()"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
222 Mutex::ScopedLock scoped_lock(per_process::umask_mutex);
223
224 uint32_t old;
225 if (args[0]->IsUndefined()) {
226 old = umask(0);
227 umask(static_cast<mode_t>(old));
228 } else {
229 int oct = args[0].As<Uint32>()->Value();
230 old = umask(static_cast<mode_t>(oct));
231 }
232
233 args.GetReturnValue().Set(old);
234}
235
236static void Uptime(const FunctionCallbackInfo<Value>& args) {
237 Environment* env = Environment::GetCurrent(args);
238
239 uv_update_time(env->event_loop());
240 double uptime =
241 static_cast<double>(uv_hrtime() - per_process::node_start_time);
242 Local<Number> result = Number::New(env->isolate(), uptime / NANOS_PER_SEC1000000000);
243 args.GetReturnValue().Set(result);
244}
245
246static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
247 Environment* env = Environment::GetCurrent(args);
248
249 std::vector<Local<Value>> request_v;
250 for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) {
251 AsyncWrap* w = req_wrap->GetAsyncWrap();
252 if (w->persistent().IsEmpty())
253 continue;
254 request_v.emplace_back(w->GetOwner());
255 }
256
257 args.GetReturnValue().Set(
258 Array::New(env->isolate(), request_v.data(), request_v.size()));
259}
260
261static void GetActiveRequestsInfo(const FunctionCallbackInfo<Value>& args) {
262 Environment* env = Environment::GetCurrent(args);
263
264 std::vector<Local<Value>> requests_info;
265 for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) {
266 AsyncWrap* w = req_wrap->GetAsyncWrap();
267 if (w->persistent().IsEmpty()) continue;
268 requests_info.emplace_back(OneByteString(env->isolate(),
269 w->MemoryInfoName().c_str()));
270 }
271
272 args.GetReturnValue().Set(
273 Array::New(env->isolate(), requests_info.data(), requests_info.size()));
274}
275
276// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
277// implemented here for consistency with GetActiveRequests().
278void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
279 Environment* env = Environment::GetCurrent(args);
280
281 std::vector<Local<Value>> handle_v;
282 for (auto w : *env->handle_wrap_queue()) {
283 if (!HandleWrap::HasRef(w))
284 continue;
285 handle_v.emplace_back(w->GetOwner());
286 }
287 args.GetReturnValue().Set(
288 Array::New(env->isolate(), handle_v.data(), handle_v.size()));
289}
290
291void GetActiveHandlesInfo(const FunctionCallbackInfo<Value>& args) {
292 Environment* env = Environment::GetCurrent(args);
293
294 std::vector<Local<Value>> handles_info;
295 for (HandleWrap* w : *env->handle_wrap_queue()) {
296 if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w)) continue;
297 handles_info.emplace_back(OneByteString(env->isolate(),
298 w->MemoryInfoName().c_str()));
299 }
300
301 args.GetReturnValue().Set(
302 Array::New(env->isolate(), handles_info.data(), handles_info.size()));
303}
304
305static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
306 Environment* env = Environment::GetCurrent(args);
307
308 uv_rusage_t rusage;
309 int err = uv_getrusage(&rusage);
310 if (err)
311 return env->ThrowUVException(err, "uv_getrusage");
312
313 Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 16);
314 double* fields = static_cast<double*>(ab->GetBackingStore()->Data());
315
316 fields[0] = MICROS_PER_SEC1e6 * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
317 fields[1] = MICROS_PER_SEC1e6 * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
318 fields[2] = static_cast<double>(rusage.ru_maxrss);
319 fields[3] = static_cast<double>(rusage.ru_ixrss);
320 fields[4] = static_cast<double>(rusage.ru_idrss);
321 fields[5] = static_cast<double>(rusage.ru_isrss);
322 fields[6] = static_cast<double>(rusage.ru_minflt);
323 fields[7] = static_cast<double>(rusage.ru_majflt);
324 fields[8] = static_cast<double>(rusage.ru_nswap);
325 fields[9] = static_cast<double>(rusage.ru_inblock);
326 fields[10] = static_cast<double>(rusage.ru_oublock);
327 fields[11] = static_cast<double>(rusage.ru_msgsnd);
328 fields[12] = static_cast<double>(rusage.ru_msgrcv);
329 fields[13] = static_cast<double>(rusage.ru_nsignals);
330 fields[14] = static_cast<double>(rusage.ru_nvcsw);
331 fields[15] = static_cast<double>(rusage.ru_nivcsw);
332}
333
334#ifdef __POSIX__1
335static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
336 Environment* env = Environment::GetCurrent(args);
337
338 if (args.Length() < 1) {
339 return THROW_ERR_MISSING_ARGS(env, "Invalid number of arguments.");
340 }
341
342 CHECK(args[0]->IsNumber())do { if (__builtin_expect(!!(!(args[0]->IsNumber())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "342", "args[0]->IsNumber()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
343 pid_t pid = args[0].As<Integer>()->Value();
344 int r = kill(pid, SIGUSR110);
345
346 if (r != 0) {
347 return env->ThrowErrnoException(errno(*__errno_location ()), "kill");
348 }
349}
350#endif // __POSIX__
351
352#ifdef _WIN32
353static int GetDebugSignalHandlerMappingName(DWORD pid,
354 wchar_t* buf,
355 size_t buf_len) {
356 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
357}
358
359static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
360 Environment* env = Environment::GetCurrent(args);
361 Isolate* isolate = args.GetIsolate();
362
363 if (args.Length() < 1) {
364 return THROW_ERR_MISSING_ARGS(env, "Invalid number of arguments.");
365 }
366
367 HANDLE process = nullptr;
368 HANDLE thread = nullptr;
369 HANDLE mapping = nullptr;
370 wchar_t mapping_name[32];
371 LPTHREAD_START_ROUTINE* handler = nullptr;
372 DWORD pid = 0;
373
374 auto cleanup = OnScopeLeave([&]() {
375 if (process != nullptr) CloseHandle(process);
376 if (thread != nullptr) CloseHandle(thread);
377 if (handler != nullptr) UnmapViewOfFile(handler);
378 if (mapping != nullptr) CloseHandle(mapping);
379 });
380
381 CHECK(args[0]->IsNumber())do { if (__builtin_expect(!!(!(args[0]->IsNumber())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "381", "args[0]->IsNumber()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
382 pid = static_cast<DWORD>(args[0].As<Integer>()->Value());
383
384 process =
385 OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
386 PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
387 FALSE,
388 pid);
389 if (process == nullptr) {
390 isolate->ThrowException(
391 WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
392 return;
393 }
394
395 if (GetDebugSignalHandlerMappingName(
396 pid, mapping_name, arraysize(mapping_name)) < 0) {
397 env->ThrowErrnoException(errno(*__errno_location ()), "sprintf");
398 return;
399 }
400
401 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
402 if (mapping == nullptr) {
403 isolate->ThrowException(
404 WinapiErrnoException(isolate, GetLastError(), "OpenFileMappingW"));
405 return;
406 }
407
408 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
409 MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, sizeof *handler));
410 if (handler == nullptr || *handler == nullptr) {
411 isolate->ThrowException(
412 WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
413 return;
414 }
415
416 thread =
417 CreateRemoteThread(process, nullptr, 0, *handler, nullptr, 0, nullptr);
418 if (thread == nullptr) {
419 isolate->ThrowException(
420 WinapiErrnoException(isolate, GetLastError(), "CreateRemoteThread"));
421 return;
422 }
423
424 // Wait for the thread to terminate
425 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
426 isolate->ThrowException(
427 WinapiErrnoException(isolate, GetLastError(), "WaitForSingleObject"));
428 return;
429 }
430}
431#endif // _WIN32
432
433static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
434#if HAVE_INSPECTOR1
435 Environment* env = Environment::GetCurrent(args);
436 if (env->inspector_agent()->IsListening()) {
437 env->inspector_agent()->Stop();
438 }
439#endif
440}
441
442static void ReallyExit(const FunctionCallbackInfo<Value>& args) {
443 Environment* env = Environment::GetCurrent(args);
444 RunAtExit(env);
445 int code = args[0]->Int32Value(env->context()).FromMaybe(0);
446 env->Exit(code);
447}
448
449namespace process {
450
451BindingData::BindingData(Environment* env, v8::Local<v8::Object> object)
452 : SnapshotableObject(env, object, type_int) {
453 Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), kBufferSize);
454 array_buffer_.Reset(env->isolate(), ab);
455 object
456 ->Set(env->context(),
457 FIXED_ONE_BYTE_STRING(env->isolate(), "hrtimeBuffer"),
458 ab)
459 .ToChecked();
460 backing_store_ = ab->GetBackingStore();
461}
462
463v8::CFunction BindingData::fast_number_(v8::CFunction::Make(FastNumber));
464v8::CFunction BindingData::fast_bigint_(v8::CFunction::Make(FastBigInt));
465
466void BindingData::AddMethods() {
467 env()->SetFastMethod(object(), "hrtime", SlowNumber, &fast_number_);
468 env()->SetFastMethod(object(), "hrtimeBigInt", SlowBigInt, &fast_bigint_);
469}
470
471void BindingData::RegisterExternalReferences(
472 ExternalReferenceRegistry* registry) {
473 registry->Register(SlowNumber);
474 registry->Register(SlowBigInt);
475 registry->Register(FastNumber);
476 registry->Register(FastBigInt);
477 registry->Register(fast_number_.GetTypeInfo());
478 registry->Register(fast_bigint_.GetTypeInfo());
479}
480
481BindingData* BindingData::FromV8Value(Local<Value> value) {
482 Local<Object> v8_object = value.As<Object>();
483 return static_cast<BindingData*>(
484 v8_object->GetAlignedPointerFromInternalField(BaseObject::kSlot));
485}
486
487void BindingData::MemoryInfo(MemoryTracker* tracker) const {
488 tracker->TrackField("array_buffer", array_buffer_);
489}
490
491// This is the legacy version of hrtime before BigInt was introduced in
492// JavaScript.
493// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
494// so this function instead fills in an Uint32Array with 3 entries,
495// to avoid any integer overflow possibility.
496// The first two entries contain the second part of the value
497// broken into the upper/lower 32 bits to be converted back in JS,
498// because there is no Uint64Array in JS.
499// The third entry contains the remaining nanosecond part of the value.
500void BindingData::NumberImpl(BindingData* receiver) {
501 // Make sure we don't accidentally access buffers wiped for snapshot.
502 CHECK(!receiver->array_buffer_.IsEmpty())do { if (__builtin_expect(!!(!(!receiver->array_buffer_.IsEmpty
())), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "502", "!receiver->array_buffer_.IsEmpty()", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
503 uint64_t t = uv_hrtime();
504 uint32_t* fields = static_cast<uint32_t*>(receiver->backing_store_->Data());
505 fields[0] = (t / NANOS_PER_SEC1000000000) >> 32;
506 fields[1] = (t / NANOS_PER_SEC1000000000) & 0xffffffff;
507 fields[2] = t % NANOS_PER_SEC1000000000;
508}
509
510void BindingData::BigIntImpl(BindingData* receiver) {
511 // Make sure we don't accidentally access buffers wiped for snapshot.
512 CHECK(!receiver->array_buffer_.IsEmpty())do { if (__builtin_expect(!!(!(!receiver->array_buffer_.IsEmpty
())), 0)) { do { static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "512", "!receiver->array_buffer_.IsEmpty()", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
513 uint64_t t = uv_hrtime();
514 uint64_t* fields = static_cast<uint64_t*>(receiver->backing_store_->Data());
515 fields[0] = t;
516}
517
518void BindingData::SlowBigInt(const FunctionCallbackInfo<Value>& args) {
519 BigIntImpl(FromJSObject<BindingData>(args.Holder()));
520}
521
522void BindingData::SlowNumber(const v8::FunctionCallbackInfo<v8::Value>& args) {
523 NumberImpl(FromJSObject<BindingData>(args.Holder()));
524}
525
526void BindingData::PrepareForSerialization(Local<Context> context,
527 v8::SnapshotCreator* creator) {
528 // It's not worth keeping.
529 // Release it, we will recreate it when the instance is dehydrated.
530 array_buffer_.Reset();
531}
532
533InternalFieldInfo* BindingData::Serialize(int index) {
534 DCHECK_EQ(index, BaseObject::kSlot);
535 InternalFieldInfo* info = InternalFieldInfo::New(type());
536 return info;
537}
538
539void BindingData::Deserialize(Local<Context> context,
540 Local<Object> holder,
541 int index,
542 InternalFieldInfo* info) {
543 DCHECK_EQ(index, BaseObject::kSlot);
544 v8::HandleScope scope(context->GetIsolate());
545 Environment* env = Environment::GetCurrent(context);
546 // Recreate the buffer in the constructor.
547 BindingData* binding = env->AddBindingData<BindingData>(context, holder);
548 CHECK_NOT_NULL(binding)do { if (__builtin_expect(!!(!((binding) != nullptr)), 0)) { do
{ static const node::AssertionInfo args = { "../src/node_process_methods.cc"
":" "548", "(binding) != nullptr", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
549}
550
551static void Initialize(Local<Object> target,
552 Local<Value> unused,
553 Local<Context> context,
554 void* priv) {
555 Environment* env = Environment::GetCurrent(context);
556 BindingData* const binding_data =
557 env->AddBindingData<BindingData>(context, target);
558 if (binding_data == nullptr) return;
559 binding_data->AddMethods();
560
561 // define various internal methods
562 if (env->owns_process_state()) {
563 env->SetMethod(target, "_debugProcess", DebugProcess);
564 env->SetMethod(target, "_debugEnd", DebugEnd);
565 env->SetMethod(target, "abort", Abort);
566 env->SetMethod(target, "causeSegfault", CauseSegfault);
567 env->SetMethod(target, "chdir", Chdir);
568 }
569
570 env->SetMethod(target, "umask", Umask);
571 env->SetMethod(target, "_rawDebug", RawDebug);
572 env->SetMethod(target, "memoryUsage", MemoryUsage);
573 env->SetMethod(target, "rss", Rss);
574 env->SetMethod(target, "cpuUsage", CPUUsage);
575 env->SetMethod(target, "resourceUsage", ResourceUsage);
576
577 env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
578 env->SetMethod(target, "_getActiveRequestsInfo", GetActiveRequestsInfo);
579 env->SetMethod(target, "_getActiveHandles", GetActiveHandles);
580 env->SetMethod(target, "_getActiveHandlesInfo", GetActiveHandlesInfo);
581 env->SetMethod(target, "_kill", Kill);
582
583 env->SetMethodNoSideEffect(target, "cwd", Cwd);
584 env->SetMethod(target, "dlopen", binding::DLOpen);
585 env->SetMethod(target, "reallyExit", ReallyExit);
586 env->SetMethodNoSideEffect(target, "uptime", Uptime);
587 env->SetMethod(target, "patchProcessObject", PatchProcessObject);
588}
589
590void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
591 BindingData::RegisterExternalReferences(registry);
592
593 registry->Register(DebugProcess);
594 registry->Register(DebugEnd);
595 registry->Register(Abort);
596 registry->Register(CauseSegfault);
597 registry->Register(Chdir);
598
599 registry->Register(Umask);
600 registry->Register(RawDebug);
601 registry->Register(MemoryUsage);
602 registry->Register(Rss);
603 registry->Register(CPUUsage);
604 registry->Register(ResourceUsage);
605
606 registry->Register(GetActiveRequests);
607 registry->Register(GetActiveRequestsInfo);
608 registry->Register(GetActiveHandles);
609 registry->Register(GetActiveHandlesInfo);
610 registry->Register(Kill);
611
612 registry->Register(Cwd);
613 registry->Register(binding::DLOpen);
614 registry->Register(ReallyExit);
615 registry->Register(Uptime);
616 registry->Register(PatchProcessObject);
617}
618
619} // namespace process
620} // namespace node
621
622NODE_MODULE_CONTEXT_AWARE_INTERNAL(process_methods, node::process::Initialize)static node::node_module _module = { 108, NM_F_INTERNAL, nullptr
, "../src/node_process_methods.cc", nullptr, (node::addon_context_register_func
)(node::process::Initialize), "process_methods", nullptr, nullptr
}; void _register_process_methods() { node_module_register(&
_module); }
623NODE_MODULE_EXTERNAL_REFERENCE(process_methods,void _register_external_reference_process_methods( node::ExternalReferenceRegistry
* registry) { node::process::RegisterExternalReferences(registry
); }
624 node::process::RegisterExternalReferences)void _register_external_reference_process_methods( node::ExternalReferenceRegistry
* registry) { node::process::RegisterExternalReferences(registry
); }