@@ -5574,11 +5574,18 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
55745574//  Only instantiate within a valid HandleScope.
55755575class  RandomBytesRequest  : public  AsyncWrap  {
55765576 public: 
5577-   RandomBytesRequest (Environment* env, Local<Object> object, size_t  size)
5577+   enum  FreeMode { FREE_DATA, DONT_FREE_DATA };
5578+ 
5579+   RandomBytesRequest (Environment* env,
5580+                      Local<Object> object,
5581+                      size_t  size,
5582+                      char * data,
5583+                      FreeMode free_mode)
55785584      : AsyncWrap(env, object, AsyncWrap::PROVIDER_CRYPTO),
55795585        error_ (0 ),
55805586        size_(size),
5581-         data_(node::Malloc(size)) {
5587+         data_(data),
5588+         free_mode_(free_mode) {
55825589    Wrap (object, this );
55835590  }
55845591
@@ -5599,9 +5606,15 @@ class RandomBytesRequest : public AsyncWrap {
55995606    return  data_;
56005607  }
56015608
5609+   inline  void  set_data (char * data) {
5610+     data_ = data;
5611+   }
5612+ 
56025613  inline  void  release () {
5603-     free (data_);
56045614    size_ = 0 ;
5615+     if  (free_mode_ == FREE_DATA) {
5616+       free (data_);
5617+     }
56055618  }
56065619
56075620  inline  void  return_memory (char ** d, size_t * len) {
@@ -5627,6 +5640,7 @@ class RandomBytesRequest : public AsyncWrap {
56275640  unsigned  long  error_;  //  NOLINT(runtime/int)
56285641  size_t  size_;
56295642  char * data_;
5643+   const  FreeMode free_mode_;
56305644};
56315645
56325646
@@ -5665,7 +5679,18 @@ void RandomBytesCheck(RandomBytesRequest* req, Local<Value> argv[2]) {
56655679    size_t  size;
56665680    req->return_memory (&data, &size);
56675681    argv[0 ] = Null (req->env ()->isolate ());
5668-     argv[1 ] = Buffer::New (req->env (), data, size).ToLocalChecked ();
5682+     Local<Value> buffer =
5683+         req->object ()->Get (req->env ()->context (),
5684+                            req->env ()->buffer_string ()).ToLocalChecked ();
5685+ 
5686+     if  (buffer->IsUint8Array ()) {
5687+       CHECK_LE (req->size (), Buffer::Length (buffer));
5688+       char * buf = Buffer::Data (buffer);
5689+       memcpy (buf, data, req->size ());
5690+       argv[1 ] = buffer;
5691+     } else  {
5692+       argv[1 ] = Buffer::New (req->env (), data, size).ToLocalChecked ();
5693+     }
56695694  }
56705695}
56715696
@@ -5684,11 +5709,22 @@ void RandomBytesAfter(uv_work_t* work_req, int status) {
56845709}
56855710
56865711
5712+ void  RandomBytesProcessSync (Environment* env,
5713+                             RandomBytesRequest* req,
5714+                             Local<Value> argv[2 ]) {
5715+   env->PrintSyncTrace ();
5716+   RandomBytesWork (req->work_req ());
5717+   RandomBytesCheck (req, argv);
5718+   delete  req;
5719+ 
5720+   if  (!argv[0 ]->IsNull ())
5721+     env->isolate ()->ThrowException (argv[0 ]);
5722+ }
5723+ 
5724+ 
56875725void  RandomBytes (const  FunctionCallbackInfo<Value>& args) {
56885726  Environment* env = Environment::GetCurrent (args);
56895727
5690-   //  maybe allow a buffer to write to? cuts down on object creation
5691-   //  when generating random data in a loop
56925728  if  (!args[0 ]->IsUint32 ()) {
56935729    return  env->ThrowTypeError (" size must be a number >= 0" 
56945730  }
@@ -5698,7 +5734,13 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
56985734    return  env->ThrowRangeError (" size is not a valid Smi" 
56995735
57005736  Local<Object> obj = env->NewInternalFieldObject ();
5701-   RandomBytesRequest* req = new  RandomBytesRequest (env, obj, size);
5737+   char * data = node::Malloc (size);
5738+   RandomBytesRequest* req =
5739+       new  RandomBytesRequest (env,
5740+                              obj,
5741+                              size,
5742+                              data,
5743+                              RandomBytesRequest::FREE_DATA);
57025744
57035745  if  (args[1 ]->IsFunction ()) {
57045746    obj->Set (env->ondone_string (), args[1 ]);
@@ -5711,15 +5753,55 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
57115753                  RandomBytesAfter);
57125754    args.GetReturnValue ().Set (obj);
57135755  } else  {
5714-     env->PrintSyncTrace ();
57155756    Local<Value> argv[2 ];
5716-     RandomBytesWork (req->work_req ());
5717-     RandomBytesCheck (req, argv);
5718-     delete  req;
5757+     RandomBytesProcessSync (env, req, argv);
5758+     if  (argv[0 ]->IsNull ())
5759+       args.GetReturnValue ().Set (argv[1 ]);
5760+   }
5761+ }
57195762
5720-     if  (!argv[0 ]->IsNull ())
5721-       env->isolate ()->ThrowException (argv[0 ]);
5722-     else 
5763+ 
5764+ void  RandomBytesBuffer (const  FunctionCallbackInfo<Value>& args) {
5765+   Environment* env = Environment::GetCurrent (args);
5766+ 
5767+   CHECK (args[0 ]->IsUint8Array ());
5768+   CHECK (args[1 ]->IsUint32 ());
5769+   CHECK (args[2 ]->IsUint32 ());
5770+ 
5771+   int64_t  offset = args[1 ]->IntegerValue ();
5772+   int64_t  size = args[2 ]->IntegerValue ();
5773+ 
5774+   Local<Object> obj = env->NewInternalFieldObject ();
5775+   obj->Set (env->context (), env->buffer_string (), args[0 ]).FromJust ();
5776+   char * data = Buffer::Data (args[0 ]);
5777+   data += offset;
5778+ 
5779+   RandomBytesRequest* req =
5780+       new  RandomBytesRequest (env,
5781+                              obj,
5782+                              size,
5783+                              data,
5784+                              RandomBytesRequest::DONT_FREE_DATA);
5785+   if  (args[3 ]->IsFunction ()) {
5786+     obj->Set (env->context (),
5787+              FIXED_ONE_BYTE_STRING (args.GetIsolate (), " ondone" 
5788+              args[3 ]).FromJust ();
5789+ 
5790+     if  (env->in_domain ()) {
5791+       obj->Set (env->context (),
5792+                env->domain_string (),
5793+                env->domain_array ()->Get (0 )).FromJust ();
5794+     }
5795+ 
5796+     uv_queue_work (env->event_loop (),
5797+                   req->work_req (),
5798+                   RandomBytesWork,
5799+                   RandomBytesAfter);
5800+     args.GetReturnValue ().Set (obj);
5801+   } else  {
5802+     Local<Value> argv[2 ];
5803+     RandomBytesProcessSync (env, req, argv);
5804+     if  (argv[0 ]->IsNull ())
57235805      args.GetReturnValue ().Set (argv[1 ]);
57245806  }
57255807}
@@ -6144,6 +6226,7 @@ void InitCrypto(Local<Object> target,
61446226  env->SetMethod (target, " setFipsCrypto" 
61456227  env->SetMethod (target, " PBKDF2" 
61466228  env->SetMethod (target, " randomBytes" 
6229+   env->SetMethod (target, " randomFill" 
61476230  env->SetMethod (target, " timingSafeEqual" 
61486231  env->SetMethod (target, " getSSLCiphers" 
61496232  env->SetMethod (target, " getCiphers" 
0 commit comments