@@ -5595,11 +5595,18 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
55955595// Only instantiate within a valid HandleScope.
55965596class RandomBytesRequest : public AsyncWrap {
55975597 public:
5598- RandomBytesRequest (Environment* env, Local<Object> object, size_t size)
5598+ enum FreeMode { FREE_DATA, DONT_FREE_DATA };
5599+
5600+ RandomBytesRequest (Environment* env,
5601+ Local<Object> object,
5602+ size_t size,
5603+ char * data,
5604+ FreeMode free_mode)
55995605 : AsyncWrap(env, object, AsyncWrap::PROVIDER_CRYPTO),
56005606 error_ (0 ),
56015607 size_(size),
5602- data_(node::Malloc(size)) {
5608+ data_(data),
5609+ free_mode_(free_mode) {
56035610 Wrap (object, this );
56045611 }
56055612
@@ -5620,9 +5627,15 @@ class RandomBytesRequest : public AsyncWrap {
56205627 return data_;
56215628 }
56225629
5630+ inline void set_data (char * data) {
5631+ data_ = data;
5632+ }
5633+
56235634 inline void release () {
5624- free (data_);
56255635 size_ = 0 ;
5636+ if (free_mode_ == FREE_DATA) {
5637+ free (data_);
5638+ }
56265639 }
56275640
56285641 inline void return_memory (char ** d, size_t * len) {
@@ -5648,6 +5661,7 @@ class RandomBytesRequest : public AsyncWrap {
56485661 unsigned long error_; // NOLINT(runtime/int)
56495662 size_t size_;
56505663 char * data_;
5664+ const FreeMode free_mode_;
56515665};
56525666
56535667
@@ -5686,7 +5700,18 @@ void RandomBytesCheck(RandomBytesRequest* req, Local<Value> argv[2]) {
56865700 size_t size;
56875701 req->return_memory (&data, &size);
56885702 argv[0 ] = Null (req->env ()->isolate ());
5689- argv[1 ] = Buffer::New (req->env (), data, size).ToLocalChecked ();
5703+ Local<Value> buffer =
5704+ req->object ()->Get (req->env ()->context (),
5705+ req->env ()->buffer_string ()).ToLocalChecked ();
5706+
5707+ if (buffer->IsUint8Array ()) {
5708+ CHECK_LE (req->size (), Buffer::Length (buffer));
5709+ char * buf = Buffer::Data (buffer);
5710+ memcpy (buf, data, req->size ());
5711+ argv[1 ] = buffer;
5712+ } else {
5713+ argv[1 ] = Buffer::New (req->env (), data, size).ToLocalChecked ();
5714+ }
56905715 }
56915716}
56925717
@@ -5705,11 +5730,22 @@ void RandomBytesAfter(uv_work_t* work_req, int status) {
57055730}
57065731
57075732
5733+ void RandomBytesProcessSync (Environment* env,
5734+ RandomBytesRequest* req,
5735+ Local<Value> argv[2 ]) {
5736+ env->PrintSyncTrace ();
5737+ RandomBytesWork (req->work_req ());
5738+ RandomBytesCheck (req, argv);
5739+ delete req;
5740+
5741+ if (!argv[0 ]->IsNull ())
5742+ env->isolate ()->ThrowException (argv[0 ]);
5743+ }
5744+
5745+
57085746void RandomBytes (const FunctionCallbackInfo<Value>& args) {
57095747 Environment* env = Environment::GetCurrent (args);
57105748
5711- // maybe allow a buffer to write to? cuts down on object creation
5712- // when generating random data in a loop
57135749 if (!args[0 ]->IsUint32 ()) {
57145750 return env->ThrowTypeError (" size must be a number >= 0" );
57155751 }
@@ -5719,7 +5755,13 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
57195755 return env->ThrowRangeError (" size is not a valid Smi" );
57205756
57215757 Local<Object> obj = env->NewInternalFieldObject ();
5722- RandomBytesRequest* req = new RandomBytesRequest (env, obj, size);
5758+ char * data = node::Malloc (size);
5759+ RandomBytesRequest* req =
5760+ new RandomBytesRequest (env,
5761+ obj,
5762+ size,
5763+ data,
5764+ RandomBytesRequest::FREE_DATA);
57235765
57245766 if (args[1 ]->IsFunction ()) {
57255767 obj->Set (FIXED_ONE_BYTE_STRING (args.GetIsolate (), " ondone" ), args[1 ]);
@@ -5732,15 +5774,55 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
57325774 RandomBytesAfter);
57335775 args.GetReturnValue ().Set (obj);
57345776 } else {
5735- env->PrintSyncTrace ();
57365777 Local<Value> argv[2 ];
5737- RandomBytesWork (req->work_req ());
5738- RandomBytesCheck (req, argv);
5739- delete req;
5778+ RandomBytesProcessSync (env, req, argv);
5779+ if (argv[0 ]->IsNull ())
5780+ args.GetReturnValue ().Set (argv[1 ]);
5781+ }
5782+ }
57405783
5741- if (!argv[0 ]->IsNull ())
5742- env->isolate ()->ThrowException (argv[0 ]);
5743- else
5784+
5785+ void RandomBytesBuffer (const FunctionCallbackInfo<Value>& args) {
5786+ Environment* env = Environment::GetCurrent (args);
5787+
5788+ CHECK (args[0 ]->IsUint8Array ());
5789+ CHECK (args[1 ]->IsUint32 ());
5790+ CHECK (args[2 ]->IsUint32 ());
5791+
5792+ int64_t offset = args[1 ]->IntegerValue ();
5793+ int64_t size = args[2 ]->IntegerValue ();
5794+
5795+ Local<Object> obj = env->NewInternalFieldObject ();
5796+ obj->Set (env->context (), env->buffer_string (), args[0 ]).FromJust ();
5797+ char * data = Buffer::Data (args[0 ]);
5798+ data += offset;
5799+
5800+ RandomBytesRequest* req =
5801+ new RandomBytesRequest (env,
5802+ obj,
5803+ size,
5804+ data,
5805+ RandomBytesRequest::DONT_FREE_DATA);
5806+ if (args[3 ]->IsFunction ()) {
5807+ obj->Set (env->context (),
5808+ FIXED_ONE_BYTE_STRING (args.GetIsolate (), " ondone" ),
5809+ args[3 ]).FromJust ();
5810+
5811+ if (env->in_domain ()) {
5812+ obj->Set (env->context (),
5813+ env->domain_string (),
5814+ env->domain_array ()->Get (0 )).FromJust ();
5815+ }
5816+
5817+ uv_queue_work (env->event_loop (),
5818+ req->work_req (),
5819+ RandomBytesWork,
5820+ RandomBytesAfter);
5821+ args.GetReturnValue ().Set (obj);
5822+ } else {
5823+ Local<Value> argv[2 ];
5824+ RandomBytesProcessSync (env, req, argv);
5825+ if (argv[0 ]->IsNull ())
57445826 args.GetReturnValue ().Set (argv[1 ]);
57455827 }
57465828}
@@ -6168,6 +6250,7 @@ void InitCrypto(Local<Object> target,
61686250 env->SetMethod (target, " setFipsCrypto" , SetFipsCrypto);
61696251 env->SetMethod (target, " PBKDF2" , PBKDF2);
61706252 env->SetMethod (target, " randomBytes" , RandomBytes);
6253+ env->SetMethod (target, " randomFill" , RandomBytesBuffer);
61716254 env->SetMethod (target, " timingSafeEqual" , TimingSafeEqual);
61726255 env->SetMethod (target, " getSSLCiphers" , GetSSLCiphers);
61736256 env->SetMethod (target, " getCiphers" , GetCiphers);
0 commit comments