@@ -82,7 +82,6 @@ using v8::NewStringType;
8282using v8::Nothing;
8383using v8::Null;
8484using v8::Object;
85- using v8::ObjectTemplate;
8685using v8::PropertyAttribute;
8786using v8::ReadOnly;
8887using v8::Signature;
@@ -4586,208 +4585,50 @@ inline void CopyBuffer(Local<Value> buf, std::vector<char>* vec) {
45864585}
45874586
45884587
4589- // Only instantiate within a valid HandleScope.
4590- class RandomBytesRequest : public AsyncWrap , public ThreadPoolWork {
4591- public:
4592- enum FreeMode { FREE_DATA, DONT_FREE_DATA };
4593-
4594- RandomBytesRequest (Environment* env,
4595- Local<Object> object,
4596- size_t size,
4597- char * data,
4598- FreeMode free_mode)
4599- : AsyncWrap(env, object, AsyncWrap::PROVIDER_RANDOMBYTESREQUEST),
4600- ThreadPoolWork (env),
4601- error_(0 ),
4602- size_(size),
4603- data_(data),
4604- free_mode_(free_mode) {
4605- }
4606-
4607- inline size_t size () const {
4608- return size_;
4609- }
4610-
4611- inline char * data () const {
4612- return data_;
4613- }
4614-
4615- inline void set_data (char * data) {
4616- data_ = data;
4617- }
4588+ struct RandomBytesJob : public CryptoJob {
4589+ unsigned char * data;
4590+ size_t size;
4591+ CryptoErrorVector errors;
4592+ Maybe<int > rc;
46184593
4619- inline void release () {
4620- size_ = 0 ;
4621- if (free_mode_ == FREE_DATA) {
4622- free (data_);
4623- data_ = nullptr ;
4624- }
4625- }
4594+ inline explicit RandomBytesJob (Environment* env)
4595+ : CryptoJob(env), rc(Nothing<int >()) {}
46264596
4627- inline void return_memory (char ** d, size_t * len) {
4628- *d = data_;
4629- data_ = nullptr ;
4630- *len = size_;
4631- size_ = 0 ;
4597+ inline void DoThreadPoolWork () override {
4598+ CheckEntropy (); // Ensure that OpenSSL's PRNG is properly seeded.
4599+ rc = Just (RAND_bytes (data, size));
4600+ if (0 == rc.FromJust ()) errors.Capture ();
46324601 }
46334602
4634- inline unsigned long error () const { // NOLINT(runtime/int)
4635- return error_;
4603+ inline void AfterThreadPoolWork () override {
4604+ Local<Value> arg = ToResult ();
4605+ async_wrap->MakeCallback (env->ondone_string (), 1 , &arg);
46364606 }
46374607
4638- inline void set_error (unsigned long err) { // NOLINT(runtime/int)
4639- error_ = err;
4608+ inline Local<Value> ToResult () const {
4609+ if (errors.empty ()) return Undefined (env->isolate ());
4610+ return errors.ToException (env);
46404611 }
4641-
4642- size_t self_size () const override { return sizeof (*this ); }
4643-
4644- void DoThreadPoolWork () override ;
4645- void AfterThreadPoolWork (int status) override ;
4646-
4647- private:
4648- unsigned long error_; // NOLINT(runtime/int)
4649- size_t size_;
4650- char * data_;
4651- const FreeMode free_mode_;
46524612};
46534613
46544614
4655- void RandomBytesRequest::DoThreadPoolWork () {
4656- // Ensure that OpenSSL's PRNG is properly seeded.
4657- CheckEntropy ();
4658-
4659- const int r = RAND_bytes (reinterpret_cast <unsigned char *>(data_), size_);
4660-
4661- // RAND_bytes() returns 0 on error.
4662- if (r == 0 ) {
4663- set_error (ERR_get_error ()); // NOLINT(runtime/int)
4664- } else if (r == -1 ) {
4665- set_error (static_cast <unsigned long >(-1 )); // NOLINT(runtime/int)
4666- }
4667- }
4668-
4669-
4670- // don't call this function without a valid HandleScope
4671- void RandomBytesCheck (RandomBytesRequest* req, Local<Value> (*argv)[2]) {
4672- if (req->error ()) {
4673- char errmsg[256 ] = " Operation not supported" ;
4674-
4675- if (req->error () != static_cast <unsigned long >(-1 )) // NOLINT(runtime/int)
4676- ERR_error_string_n (req->error (), errmsg, sizeof errmsg);
4677-
4678- (*argv)[0 ] = Exception::Error (OneByteString (req->env ()->isolate (), errmsg));
4679- (*argv)[1 ] = Null (req->env ()->isolate ());
4680- req->release ();
4681- } else {
4682- char * data = nullptr ;
4683- size_t size;
4684- req->return_memory (&data, &size);
4685- (*argv)[0 ] = Null (req->env ()->isolate ());
4686- Local<Value> buffer =
4687- req->object ()->Get (req->env ()->context (),
4688- req->env ()->buffer_string ()).ToLocalChecked ();
4689-
4690- if (buffer->IsArrayBufferView ()) {
4691- CHECK_LE (req->size (), Buffer::Length (buffer));
4692- char * buf = Buffer::Data (buffer);
4693- memcpy (buf, data, req->size ());
4694- (*argv)[1 ] = buffer;
4695- } else {
4696- (*argv)[1 ] = Buffer::New (req->env (), data, size)
4697- .ToLocalChecked ();
4698- }
4699- }
4700- }
4701-
4702-
4703- void RandomBytesRequest::AfterThreadPoolWork (int status) {
4704- std::unique_ptr<RandomBytesRequest> req (this );
4705- if (status == UV_ECANCELED)
4706- return ;
4707- CHECK_EQ (status, 0 );
4708- HandleScope handle_scope (env ()->isolate ());
4709- Context::Scope context_scope (env ()->context ());
4710- Local<Value> argv[2 ];
4711- RandomBytesCheck (this , &argv);
4712- MakeCallback (env ()->ondone_string (), arraysize (argv), argv);
4713- }
4714-
4715-
4716- void RandomBytesProcessSync (Environment* env,
4717- std::unique_ptr<RandomBytesRequest> req,
4718- Local<Value> (*argv)[2]) {
4719- env->PrintSyncTrace ();
4720- req->DoThreadPoolWork ();
4721- RandomBytesCheck (req.get (), argv);
4722-
4723- if (!(*argv)[0 ]->IsNull ())
4724- env->isolate ()->ThrowException ((*argv)[0 ]);
4725- }
4726-
4727-
47284615void RandomBytes (const FunctionCallbackInfo<Value>& args) {
4616+ CHECK (args[0 ]->IsArrayBufferView ()); // buffer; wrap object retains ref.
4617+ CHECK (args[1 ]->IsUint32 ()); // offset
4618+ CHECK (args[2 ]->IsUint32 ()); // size
4619+ CHECK (args[3 ]->IsObject () || args[3 ]->IsUndefined ()); // wrap object
4620+ const uint32_t offset = args[1 ].As <Uint32>()->Value ();
4621+ const uint32_t size = args[2 ].As <Uint32>()->Value ();
4622+ CHECK_GE (offset + size, offset); // Overflow check.
4623+ CHECK_LE (offset + size, Buffer::Length (args[0 ])); // Bounds check.
47294624 Environment* env = Environment::GetCurrent (args);
4730-
4731- const int64_t size = args[0 ]->IntegerValue ();
4732- CHECK (size <= Buffer::kMaxLength );
4733-
4734- Local<Object> obj = env->randombytes_constructor_template ()->
4735- NewInstance (env->context ()).ToLocalChecked ();
4736- char * data = node::Malloc (size);
4737- std::unique_ptr<RandomBytesRequest> req (
4738- new RandomBytesRequest (env,
4739- obj,
4740- size,
4741- data,
4742- RandomBytesRequest::FREE_DATA));
4743-
4744- if (args[1 ]->IsFunction ()) {
4745- obj->Set (env->context (), env->ondone_string (), args[1 ]).FromJust ();
4746-
4747- req.release ()->ScheduleWork ();
4748- args.GetReturnValue ().Set (obj);
4749- } else {
4750- Local<Value> argv[2 ];
4751- RandomBytesProcessSync (env, std::move (req), &argv);
4752- if (argv[0 ]->IsNull ())
4753- args.GetReturnValue ().Set (argv[1 ]);
4754- }
4755- }
4756-
4757-
4758- void RandomBytesBuffer (const FunctionCallbackInfo<Value>& args) {
4759- Environment* env = Environment::GetCurrent (args);
4760-
4761- CHECK (args[0 ]->IsArrayBufferView ());
4762- CHECK (args[1 ]->IsUint32 ());
4763- CHECK (args[2 ]->IsUint32 ());
4764-
4765- int64_t offset = args[1 ]->IntegerValue ();
4766- int64_t size = args[2 ]->IntegerValue ();
4767-
4768- Local<Object> obj = env->randombytes_constructor_template ()->
4769- NewInstance (env->context ()).ToLocalChecked ();
4770- obj->Set (env->context (), env->buffer_string (), args[0 ]).FromJust ();
4771- char * data = Buffer::Data (args[0 ]);
4772- data += offset;
4773-
4774- std::unique_ptr<RandomBytesRequest> req (
4775- new RandomBytesRequest (env,
4776- obj,
4777- size,
4778- data,
4779- RandomBytesRequest::DONT_FREE_DATA));
4780- if (args[3 ]->IsFunction ()) {
4781- obj->Set (env->context (), env->ondone_string (), args[3 ]).FromJust ();
4782-
4783- req.release ()->ScheduleWork ();
4784- args.GetReturnValue ().Set (obj);
4785- } else {
4786- Local<Value> argv[2 ];
4787- RandomBytesProcessSync (env, std::move (req), &argv);
4788- if (argv[0 ]->IsNull ())
4789- args.GetReturnValue ().Set (argv[1 ]);
4790- }
4625+ std::unique_ptr<RandomBytesJob> job (new RandomBytesJob (env));
4626+ job->data = reinterpret_cast <unsigned char *>(Buffer::Data (args[0 ])) + offset;
4627+ job->size = size;
4628+ if (args[3 ]->IsObject ()) return RandomBytesJob::Run (std::move (job), args[3 ]);
4629+ env->PrintSyncTrace ();
4630+ job->DoThreadPoolWork ();
4631+ args.GetReturnValue ().Set (job->ToResult ());
47914632}
47924633
47934634
@@ -5352,7 +5193,6 @@ void Initialize(Local<Object> target,
53525193
53535194 env->SetMethod (target, " pbkdf2" , PBKDF2);
53545195 env->SetMethod (target, " randomBytes" , RandomBytes);
5355- env->SetMethod (target, " randomFill" , RandomBytesBuffer);
53565196 env->SetMethod (target, " timingSafeEqual" , TimingSafeEqual);
53575197 env->SetMethod (target, " getSSLCiphers" , GetSSLCiphers);
53585198 env->SetMethod (target, " getCiphers" , GetCiphers);
@@ -5377,13 +5217,6 @@ void Initialize(Local<Object> target,
53775217#ifndef OPENSSL_NO_SCRYPT
53785218 env->SetMethod (target, " scrypt" , Scrypt);
53795219#endif // OPENSSL_NO_SCRYPT
5380-
5381- Local<FunctionTemplate> rb = FunctionTemplate::New (env->isolate ());
5382- rb->SetClassName (FIXED_ONE_BYTE_STRING (env->isolate (), " RandomBytes" ));
5383- AsyncWrap::AddWrapMethods (env, rb);
5384- Local<ObjectTemplate> rbt = rb->InstanceTemplate ();
5385- rbt->SetInternalFieldCount (1 );
5386- env->set_randombytes_constructor_template (rbt);
53875220}
53885221
53895222} // namespace crypto
0 commit comments