Skip to content

Commit fcf0e8e

Browse files
Matt Loringrvagg
Matt Loring
authored andcommitted
buffer: move checkFloat from lib into src
The type and range checks performed by this function can be done more efficiently in native code. PR-URL: #3763 Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent f90227b commit fcf0e8e

File tree

2 files changed

+42
-29
lines changed

2 files changed

+42
-29
lines changed

lib/buffer.js

+12-16
Original file line numberDiff line numberDiff line change
@@ -1028,20 +1028,13 @@ Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
10281028
};
10291029

10301030

1031-
function checkFloat(buffer, value, offset, ext) {
1032-
if (!(buffer instanceof Buffer))
1033-
throw new TypeError('buffer must be a Buffer instance');
1034-
if (offset + ext > buffer.length)
1035-
throw new RangeError('index out of range');
1036-
}
1037-
1038-
10391031
Buffer.prototype.writeFloatLE = function writeFloatLE(val, offset, noAssert) {
10401032
val = +val;
10411033
offset = offset >>> 0;
10421034
if (!noAssert)
1043-
checkFloat(this, val, offset, 4);
1044-
binding.writeFloatLE(this, val, offset);
1035+
binding.writeFloatLE(this, val, offset);
1036+
else
1037+
binding.writeFloatLE(this, val, offset, true);
10451038
return offset + 4;
10461039
};
10471040

@@ -1050,8 +1043,9 @@ Buffer.prototype.writeFloatBE = function writeFloatBE(val, offset, noAssert) {
10501043
val = +val;
10511044
offset = offset >>> 0;
10521045
if (!noAssert)
1053-
checkFloat(this, val, offset, 4);
1054-
binding.writeFloatBE(this, val, offset);
1046+
binding.writeFloatBE(this, val, offset);
1047+
else
1048+
binding.writeFloatBE(this, val, offset, true);
10551049
return offset + 4;
10561050
};
10571051

@@ -1060,8 +1054,9 @@ Buffer.prototype.writeDoubleLE = function writeDoubleLE(val, offset, noAssert) {
10601054
val = +val;
10611055
offset = offset >>> 0;
10621056
if (!noAssert)
1063-
checkFloat(this, val, offset, 8);
1064-
binding.writeDoubleLE(this, val, offset);
1057+
binding.writeDoubleLE(this, val, offset);
1058+
else
1059+
binding.writeDoubleLE(this, val, offset, true);
10651060
return offset + 8;
10661061
};
10671062

@@ -1070,7 +1065,8 @@ Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
10701065
val = +val;
10711066
offset = offset >>> 0;
10721067
if (!noAssert)
1073-
checkFloat(this, val, offset, 8);
1074-
binding.writeDoubleBE(this, val, offset);
1068+
binding.writeDoubleBE(this, val, offset);
1069+
else
1070+
binding.writeDoubleBE(this, val, offset, true);
10751071
return offset + 8;
10761072
};

src/node_buffer.cc

+30-13
Original file line numberDiff line numberDiff line change
@@ -730,15 +730,37 @@ void ReadDoubleBE(const FunctionCallbackInfo<Value>& args) {
730730

731731

732732
template <typename T, enum Endianness endianness>
733-
uint32_t WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
734-
SPREAD_ARG(args[0], ts_obj);
733+
void WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
734+
Environment* env = Environment::GetCurrent(args);
735+
736+
bool should_assert = args.Length() < 4;
737+
738+
if (should_assert) {
739+
THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
740+
}
741+
742+
Local<Uint8Array> ts_obj = args[0].As<Uint8Array>();
743+
ArrayBuffer::Contents ts_obj_c = ts_obj->Buffer()->GetContents();
744+
const size_t ts_obj_offset = ts_obj->ByteOffset();
745+
const size_t ts_obj_length = ts_obj->ByteLength();
746+
char* const ts_obj_data =
747+
static_cast<char*>(ts_obj_c.Data()) + ts_obj_offset;
748+
if (ts_obj_length > 0)
749+
CHECK_NE(ts_obj_data, nullptr);
750+
751+
T val = args[1]->NumberValue(env->context()).FromMaybe(0);
752+
size_t offset = args[2]->IntegerValue(env->context()).FromMaybe(0);
735753

736-
T val = args[1]->NumberValue();
737-
uint32_t offset = args[2]->Uint32Value();
738754
size_t memcpy_num = sizeof(T);
739755
if (offset + sizeof(T) > ts_obj_length)
740756
memcpy_num = ts_obj_length - offset;
741757

758+
if (should_assert) {
759+
CHECK_NOT_OOB(offset + memcpy_num >= memcpy_num);
760+
CHECK_NOT_OOB(offset + memcpy_num <= ts_obj_length);
761+
}
762+
CHECK_LE(offset + memcpy_num, ts_obj_length);
763+
742764
union NoAlias {
743765
T val;
744766
char bytes[sizeof(T)];
@@ -749,31 +771,26 @@ uint32_t WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
749771
if (endianness != GetEndianness())
750772
Swizzle(na.bytes, sizeof(na.bytes));
751773
memcpy(ptr, na.bytes, memcpy_num);
752-
return offset + memcpy_num;
753774
}
754775

755776

756777
void WriteFloatLE(const FunctionCallbackInfo<Value>& args) {
757-
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
758-
args.GetReturnValue().Set(WriteFloatGeneric<float, kLittleEndian>(args));
778+
WriteFloatGeneric<float, kLittleEndian>(args);
759779
}
760780

761781

762782
void WriteFloatBE(const FunctionCallbackInfo<Value>& args) {
763-
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
764-
args.GetReturnValue().Set(WriteFloatGeneric<float, kBigEndian>(args));
783+
WriteFloatGeneric<float, kBigEndian>(args);
765784
}
766785

767786

768787
void WriteDoubleLE(const FunctionCallbackInfo<Value>& args) {
769-
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
770-
args.GetReturnValue().Set(WriteFloatGeneric<double, kLittleEndian>(args));
788+
WriteFloatGeneric<double, kLittleEndian>(args);
771789
}
772790

773791

774792
void WriteDoubleBE(const FunctionCallbackInfo<Value>& args) {
775-
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
776-
args.GetReturnValue().Set(WriteFloatGeneric<double, kBigEndian>(args));
793+
WriteFloatGeneric<double, kBigEndian>(args);
777794
}
778795

779796

0 commit comments

Comments
 (0)