summaryrefslogtreecommitdiff
path: root/lib/buffer.js
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2018-01-30 17:21:28 +0100
committerRuben Bridgewater <ruben@bridgewater.de>2018-03-02 19:23:57 +0000
commit1411b30f4646878fc3ff452c3d97a240c0d8b807 (patch)
tree9f6111146f86c5288b08f23dfab0b8b39a41c432 /lib/buffer.js
parent069dd10ca2258a27f3cba2db688ce4b97b624241 (diff)
downloadandroid-node-v8-1411b30f4646878fc3ff452c3d97a240c0d8b807.tar.gz
android-node-v8-1411b30f4646878fc3ff452c3d97a240c0d8b807.tar.bz2
android-node-v8-1411b30f4646878fc3ff452c3d97a240c0d8b807.zip
buffer: move c++ float functions to js
This ports the Buffer#write(Double|Float)(B|L)E functions to JS. This fixes a security issue concerning type confusion and fixes another possible crash in combination with `noAssert`. In addition to that it will also significantly improve the write performance. Fixes: https://github.com/nodejs/node/issues/12179 Fixes: https://github.com/nodejs/node/issues/8724 PR-URL: https://github.com/nodejs/node/pull/18395 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'lib/buffer.js')
-rw-r--r--lib/buffer.js108
1 files changed, 74 insertions, 34 deletions
diff --git a/lib/buffer.js b/lib/buffer.js
index 0aa9e2001b..f36bd76acd 100644
--- a/lib/buffer.js
+++ b/lib/buffer.js
@@ -34,10 +34,6 @@ const {
swap16: _swap16,
swap32: _swap32,
swap64: _swap64,
- writeDoubleBE: _writeDoubleBE,
- writeDoubleLE: _writeDoubleLE,
- writeFloatBE: _writeFloatBE,
- writeFloatLE: _writeFloatLE,
kMaxLength,
kStringMaxLength
} = process.binding('buffer');
@@ -85,6 +81,12 @@ const constants = Object.defineProperties({}, {
}
});
+// Temporary buffers to convert numbers.
+const float32Array = new Float32Array(1);
+const uInt8Float32Array = new Uint8Array(float32Array.buffer);
+const float64Array = new Float64Array(1);
+const uInt8Float64Array = new Uint8Array(float64Array.buffer);
+
Buffer.poolSize = 8 * 1024;
var poolSize, poolOffset, allocPool;
@@ -1297,12 +1299,16 @@ Buffer.prototype.readFloatLE = function(offset, noAssert) {
return toFloat(this.readUInt32LE(offset, noAssert));
};
+function checkOOB(buffer, offset, ext) {
+ if (offset + ext > buffer.length)
+ throw new errors.RangeError('ERR_INDEX_OUT_OF_RANGE');
+}
+
function checkInt(buffer, value, offset, ext, max, min) {
if (value > max || value < min)
throw new errors.RangeError('ERR_INVALID_OPT_VALUE', 'value', value);
- if (offset + ext > buffer.length)
- throw new errors.RangeError('ERR_INDEX_OUT_OF_RANGE');
+ checkOOB(buffer, offset, ext);
}
@@ -1520,49 +1526,83 @@ Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) {
return offset + 4;
};
-
-Buffer.prototype.writeFloatLE = function writeFloatLE(val, offset, noAssert) {
+function writeDoubleForwards(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
- _writeFloatLE(this, val, offset);
- else
- _writeFloatLE(this, val, offset, true);
- return offset + 4;
-};
-
+ checkOOB(this, offset, 8);
+
+ float64Array[0] = val;
+ this[offset++] = uInt8Float64Array[0];
+ this[offset++] = uInt8Float64Array[1];
+ this[offset++] = uInt8Float64Array[2];
+ this[offset++] = uInt8Float64Array[3];
+ this[offset++] = uInt8Float64Array[4];
+ this[offset++] = uInt8Float64Array[5];
+ this[offset++] = uInt8Float64Array[6];
+ this[offset++] = uInt8Float64Array[7];
+ return offset;
+}
-Buffer.prototype.writeFloatBE = function writeFloatBE(val, offset, noAssert) {
+function writeDoubleBackwards(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
- _writeFloatBE(this, val, offset);
- else
- _writeFloatBE(this, val, offset, true);
- return offset + 4;
-};
-
+ checkOOB(this, offset, 8);
+
+ float64Array[0] = val;
+ this[offset++] = uInt8Float64Array[7];
+ this[offset++] = uInt8Float64Array[6];
+ this[offset++] = uInt8Float64Array[5];
+ this[offset++] = uInt8Float64Array[4];
+ this[offset++] = uInt8Float64Array[3];
+ this[offset++] = uInt8Float64Array[2];
+ this[offset++] = uInt8Float64Array[1];
+ this[offset++] = uInt8Float64Array[0];
+ return offset;
+}
-Buffer.prototype.writeDoubleLE = function writeDoubleLE(val, offset, noAssert) {
+function writeFloatForwards(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
- _writeDoubleLE(this, val, offset);
- else
- _writeDoubleLE(this, val, offset, true);
- return offset + 8;
-};
-
+ checkOOB(this, offset, 4);
+
+ float32Array[0] = val;
+ this[offset++] = uInt8Float32Array[0];
+ this[offset++] = uInt8Float32Array[1];
+ this[offset++] = uInt8Float32Array[2];
+ this[offset++] = uInt8Float32Array[3];
+ return offset;
+}
-Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
+function writeFloatBackwards(val, offset, noAssert) {
val = +val;
offset = offset >>> 0;
if (!noAssert)
- _writeDoubleBE(this, val, offset);
- else
- _writeDoubleBE(this, val, offset, true);
- return offset + 8;
-};
+ checkOOB(this, offset, 4);
+
+ float32Array[0] = val;
+ this[offset++] = uInt8Float32Array[3];
+ this[offset++] = uInt8Float32Array[2];
+ this[offset++] = uInt8Float32Array[1];
+ this[offset++] = uInt8Float32Array[0];
+ return offset;
+}
+
+// Check endianness.
+float32Array[0] = -1;
+if (uInt8Float32Array[3] === 0) { // Big endian.
+ Buffer.prototype.writeFloatLE = writeFloatBackwards;
+ Buffer.prototype.writeFloatBE = writeFloatForwards;
+ Buffer.prototype.writeDoubleLE = writeDoubleBackwards;
+ Buffer.prototype.writeDoubleBE = writeDoubleForwards;
+} else { // Small endian.
+ Buffer.prototype.writeFloatLE = writeFloatForwards;
+ Buffer.prototype.writeFloatBE = writeFloatBackwards;
+ Buffer.prototype.writeDoubleLE = writeDoubleForwards;
+ Buffer.prototype.writeDoubleBE = writeDoubleBackwards;
+}
function swap(b, n, m) {
const i = b[n];