Skip to content

Commit c6d29cc

Browse files
committed
buffer: do proper error propagation in addon methods
- Always fulfill the `MaybeLocal<>` contract by scheduling an exception when returning an empty value. This was previously inconsistent, with no way to know whether an exception was be scheduled or not in case of failure. - Make sure that memory is released exactly once in case of failure. Previously, some exit conditions would have leaked memory or attempted to free it multiple times. This should not really affect how `Buffer`s are created by addons in practice, due to the low frequency with which these errors would typically occur. PR-URL: #23939 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
1 parent 1c67e74 commit c6d29cc

File tree

1 file changed

+25
-23
lines changed

1 file changed

+25
-23
lines changed

src/node_buffer.cc

+25-23
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,10 @@ MaybeLocal<Object> New(Isolate* isolate,
243243
if (length > 0) {
244244
data = static_cast<char*>(BufferMalloc(length));
245245

246-
if (data == nullptr)
246+
if (data == nullptr) {
247+
THROW_ERR_MEMORY_ALLOCATION_FAILED(isolate);
247248
return Local<Object>();
249+
}
248250

249251
actual = StringBytes::Write(isolate, data, length, string, enc);
250252
CHECK(actual <= length);
@@ -286,14 +288,17 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
286288

287289
// V8 currently only allows a maximum Typed Array index of max Smi.
288290
if (length > kMaxLength) {
291+
env->isolate()->ThrowException(ERR_BUFFER_TOO_LARGE(env->isolate()));
289292
return Local<Object>();
290293
}
291294

292295
void* data;
293296
if (length > 0) {
294297
data = BufferMalloc(length);
295-
if (data == nullptr)
298+
if (data == nullptr) {
299+
THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
296300
return Local<Object>();
301+
}
297302
} else {
298303
data = nullptr;
299304
}
@@ -303,14 +308,10 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
303308
data,
304309
length,
305310
ArrayBufferCreationMode::kInternalized);
306-
MaybeLocal<Uint8Array> ui = Buffer::New(env, ab, 0, length);
307-
308-
if (ui.IsEmpty()) {
309-
// Object failed to be created. Clean up resources.
310-
free(data);
311-
}
312-
313-
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
311+
Local<Object> obj;
312+
if (Buffer::New(env, ab, 0, length).ToLocal(&obj))
313+
return scope.Escape(obj);
314+
return Local<Object>();
314315
}
315316

316317

@@ -333,15 +334,18 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
333334

334335
// V8 currently only allows a maximum Typed Array index of max Smi.
335336
if (length > kMaxLength) {
337+
env->isolate()->ThrowException(ERR_BUFFER_TOO_LARGE(env->isolate()));
336338
return Local<Object>();
337339
}
338340

339341
void* new_data;
340342
if (length > 0) {
341343
CHECK_NOT_NULL(data);
342344
new_data = node::UncheckedMalloc(length);
343-
if (new_data == nullptr)
345+
if (new_data == nullptr) {
346+
THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
344347
return Local<Object>();
348+
}
345349
memcpy(new_data, data, length);
346350
} else {
347351
new_data = nullptr;
@@ -352,14 +356,10 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
352356
new_data,
353357
length,
354358
ArrayBufferCreationMode::kInternalized);
355-
MaybeLocal<Uint8Array> ui = Buffer::New(env, ab, 0, length);
356-
357-
if (ui.IsEmpty()) {
358-
// Object failed to be created. Clean up resources.
359-
free(new_data);
360-
}
361-
362-
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
359+
Local<Object> obj;
360+
if (Buffer::New(env, ab, 0, length).ToLocal(&obj))
361+
return scope.Escape(obj);
362+
return Local<Object>();
363363
}
364364

365365

@@ -390,6 +390,8 @@ MaybeLocal<Object> New(Environment* env,
390390
EscapableHandleScope scope(env->isolate());
391391

392392
if (length > kMaxLength) {
393+
env->isolate()->ThrowException(ERR_BUFFER_TOO_LARGE(env->isolate()));
394+
callback(data, hint);
393395
return Local<Object>();
394396
}
395397

@@ -401,11 +403,11 @@ MaybeLocal<Object> New(Environment* env,
401403
ab->Neuter();
402404
MaybeLocal<Uint8Array> ui = Buffer::New(env, ab, 0, length);
403405

404-
if (ui.IsEmpty()) {
405-
return Local<Object>();
406-
}
407-
408406
CallbackInfo::New(env->isolate(), ab, callback, data, hint);
407+
408+
if (ui.IsEmpty())
409+
return MaybeLocal<Object>();
410+
409411
return scope.Escape(ui.ToLocalChecked());
410412
}
411413

0 commit comments

Comments
 (0)