@@ -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