Last active
December 9, 2016 17:38
-
-
Save evanlucas/6d9c5998100e9b1cdbea37ee7d224ad1 to your computer and use it in GitHub Desktop.
allow buffers for crypto.randomBytes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/node_crypto.cc b/src/node_crypto.cc | |
index 8f2f750..8912eea 100644 | |
--- a/src/node_crypto.cc | |
+++ b/src/node_crypto.cc | |
@@ -5503,14 +5503,21 @@ void RandomBytesCheck(RandomBytesRequest* req, Local<Value> argv[2]) { | |
ERR_error_string_n(req->error(), errmsg, sizeof errmsg); | |
argv[0] = Exception::Error(OneByteString(req->env()->isolate(), errmsg)); | |
- argv[1] = Null(req->env()->isolate()); | |
req->release(); | |
} else { | |
char* data = nullptr; | |
size_t size; | |
req->return_memory(&data, &size); | |
argv[0] = Null(req->env()->isolate()); | |
- argv[1] = Buffer::New(req->env(), data, size).ToLocalChecked(); | |
+ | |
+ if (!argv[1]->IsNull()) { | |
+ char* buf = reinterpret_cast<char*>(Buffer::Data(argv[1].As<Object>())); | |
+ for (size_t i = 0; i < size; i++) { | |
+ buf[i] = data[i]; | |
+ } | |
+ } else { | |
+ argv[1] = Buffer::New(req->env(), data, size).ToLocalChecked(); | |
+ } | |
} | |
} | |
@@ -5523,6 +5530,7 @@ void RandomBytesAfter(uv_work_t* work_req, int status) { | |
HandleScope handle_scope(env->isolate()); | |
Context::Scope context_scope(env->context()); | |
Local<Value> argv[2]; | |
+ argv[1] = Null(env->isolate()); | |
RandomBytesCheck(req, argv); | |
req->MakeCallback(env->ondone_string(), arraysize(argv), argv); | |
delete req; | |
@@ -5534,38 +5542,56 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) { | |
// maybe allow a buffer to write to? cuts down on object creation | |
// when generating random data in a loop | |
- if (!args[0]->IsUint32()) { | |
- return env->ThrowTypeError("size must be a number >= 0"); | |
+ if (!args[0]->IsUint32() && !Buffer::HasInstance(args[0])) { | |
+ return env->ThrowTypeError("size must be a number >= 0 or a buffer"); | |
} | |
- const int64_t size = args[0]->IntegerValue(); | |
- if (size < 0 || size > Buffer::kMaxLength) | |
- return env->ThrowRangeError("size is not a valid Smi"); | |
+ if (args[0]->IsUint32()) { | |
+ const int64_t size = args[0]->IntegerValue(); | |
+ if (size < 0 || size > Buffer::kMaxLength) | |
+ return env->ThrowRangeError("size is not a valid Smi"); | |
- Local<Object> obj = env->NewInternalFieldObject(); | |
- RandomBytesRequest* req = new RandomBytesRequest(env, obj, size); | |
+ Local<Object> obj = env->NewInternalFieldObject(); | |
+ RandomBytesRequest* req = new RandomBytesRequest(env, obj, size); | |
- if (args[1]->IsFunction()) { | |
- obj->Set(FIXED_ONE_BYTE_STRING(args.GetIsolate(), "ondone"), args[1]); | |
+ if (args[1]->IsFunction()) { | |
+ obj->Set(FIXED_ONE_BYTE_STRING(args.GetIsolate(), "ondone"), args[1]); | |
- if (env->in_domain()) | |
- obj->Set(env->domain_string(), env->domain_array()->Get(0)); | |
- uv_queue_work(env->event_loop(), | |
- req->work_req(), | |
- RandomBytesWork, | |
- RandomBytesAfter); | |
- args.GetReturnValue().Set(obj); | |
+ if (env->in_domain()) | |
+ obj->Set(env->domain_string(), env->domain_array()->Get(0)); | |
+ uv_queue_work(env->event_loop(), | |
+ req->work_req(), | |
+ RandomBytesWork, | |
+ RandomBytesAfter); | |
+ args.GetReturnValue().Set(obj); | |
+ } else { | |
+ env->PrintSyncTrace(); | |
+ Local<Value> argv[2]; | |
+ argv[1] = Null(env->isolate()); | |
+ RandomBytesWork(req->work_req()); | |
+ RandomBytesCheck(req, argv); | |
+ delete req; | |
+ | |
+ if (!argv[0]->IsNull()) | |
+ env->isolate()->ThrowException(argv[0]); | |
+ else | |
+ args.GetReturnValue().Set(argv[1]); | |
+ } | |
} else { | |
+ // Buffer | |
+ const int64_t size = Buffer::Length(args[0]); | |
+ Local<Object> obj = env->NewInternalFieldObject(); | |
+ RandomBytesRequest* req = new RandomBytesRequest(env, obj, size); | |
env->PrintSyncTrace(); | |
+ | |
Local<Value> argv[2]; | |
+ argv[1] = args[0]; | |
RandomBytesWork(req->work_req()); | |
RandomBytesCheck(req, argv); | |
delete req; | |
if (!argv[0]->IsNull()) | |
env->isolate()->ThrowException(argv[0]); | |
- else | |
- args.GetReturnValue().Set(argv[1]); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment