@@ -587,9 +587,9 @@ void StringSlice(const FunctionCallbackInfo<Value>& args) {
587587
588588void CopyImpl (Local<Value> source_obj,
589589 Local<Value> target_obj,
590- const uint32_t target_start,
591- const uint32_t source_start,
592- const uint32_t to_copy) {
590+ const size_t target_start,
591+ const size_t source_start,
592+ const size_t to_copy) {
593593 ArrayBufferViewContents<char > source (source_obj);
594594 SPREAD_BUFFER_ARG (target_obj, target);
595595
@@ -598,15 +598,29 @@ void CopyImpl(Local<Value> source_obj,
598598
599599// Assume caller has properly validated args.
600600void SlowCopy (const FunctionCallbackInfo<Value>& args) {
601+ Environment* env = Environment::GetCurrent (args);
601602 Local<Value> source_obj = args[0 ];
602603 Local<Value> target_obj = args[1 ];
603- const uint32_t target_start = args[2 ].As <Uint32>()->Value ();
604- const uint32_t source_start = args[3 ].As <Uint32>()->Value ();
605- const uint32_t to_copy = args[4 ].As <Uint32>()->Value ();
606-
607- CopyImpl (source_obj, target_obj, target_start, source_start, to_copy);
608-
609- args.GetReturnValue ().Set (to_copy);
604+ // Use IntegerValue() rather than Uint32Value() so that values larger than
605+ // 2**32 are not silently truncated. The JS layer is responsible for
606+ // ensuring these are non-negative safe integers.
607+ const int64_t target_start =
608+ args[2 ]->IntegerValue (env->context ()).ToChecked ();
609+ const int64_t source_start =
610+ args[3 ]->IntegerValue (env->context ()).ToChecked ();
611+ const int64_t to_copy = args[4 ]->IntegerValue (env->context ()).ToChecked ();
612+
613+ CHECK_GE (target_start, 0 );
614+ CHECK_GE (source_start, 0 );
615+ CHECK_GE (to_copy, 0 );
616+
617+ CopyImpl (source_obj,
618+ target_obj,
619+ static_cast <size_t >(target_start),
620+ static_cast <size_t >(source_start),
621+ static_cast <size_t >(to_copy));
622+
623+ args.GetReturnValue ().Set (static_cast <double >(to_copy));
610624}
611625
612626// Assume caller has properly validated args.
@@ -1480,11 +1494,12 @@ void CopyArrayBuffer(const FunctionCallbackInfo<Value>& args) {
14801494 // args[3] == Source ArrayBuffer Offset
14811495 // args[4] == bytesToCopy
14821496
1497+ Environment* env = Environment::GetCurrent (args);
14831498 CHECK (args[0 ]->IsArrayBuffer () || args[0 ]->IsSharedArrayBuffer ());
1484- CHECK (args[1 ]->IsUint32 ());
1499+ CHECK (args[1 ]->IsNumber ());
14851500 CHECK (args[2 ]->IsArrayBuffer () || args[2 ]->IsSharedArrayBuffer ());
1486- CHECK (args[3 ]->IsUint32 ());
1487- CHECK (args[4 ]->IsUint32 ());
1501+ CHECK (args[3 ]->IsNumber ());
1502+ CHECK (args[4 ]->IsNumber ());
14881503
14891504 void * destination;
14901505 size_t destination_byte_length;
@@ -1495,9 +1510,19 @@ void CopyArrayBuffer(const FunctionCallbackInfo<Value>& args) {
14951510 size_t source_byte_length;
14961511 std::tie (source, source_byte_length) = DecomposeBufferToParts (args[2 ]);
14971512
1498- uint32_t destination_offset = args[1 ].As <Uint32>()->Value ();
1499- uint32_t source_offset = args[3 ].As <Uint32>()->Value ();
1500- size_t bytes_to_copy = args[4 ].As <Uint32>()->Value ();
1513+ // Use IntegerValue() so offsets larger than 2**32 are not truncated.
1514+ const int64_t destination_offset_signed =
1515+ args[1 ]->IntegerValue (env->context ()).ToChecked ();
1516+ const int64_t source_offset_signed =
1517+ args[3 ]->IntegerValue (env->context ()).ToChecked ();
1518+ const int64_t bytes_to_copy_signed =
1519+ args[4 ]->IntegerValue (env->context ()).ToChecked ();
1520+ CHECK_GE (destination_offset_signed, 0 );
1521+ CHECK_GE (source_offset_signed, 0 );
1522+ CHECK_GE (bytes_to_copy_signed, 0 );
1523+ size_t destination_offset = static_cast <size_t >(destination_offset_signed);
1524+ size_t source_offset = static_cast <size_t >(source_offset_signed);
1525+ size_t bytes_to_copy = static_cast <size_t >(bytes_to_copy_signed);
15011526
15021527 CHECK_GE (destination_byte_length - destination_offset, bytes_to_copy);
15031528 CHECK_GE (source_byte_length - source_offset, bytes_to_copy);
0 commit comments