diff --git a/lib/buffer.js b/lib/buffer.js index 6fb7a6d993..f755d951b8 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -616,35 +616,28 @@ Buffer.prototype.asciiWrite = function(string, offset) { return this.write(string, offset, 'ascii'); }; -Buffer.prototype.readUInt8 = function(offset, noAssert) { - var buffer = this; - if (!noAssert) { - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); +/* + * Need to make sure that buffer isn't trying to write out of bounds. + * This check is far too slow internally for fast buffers. + */ +function checkOffset(offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) + throw new RangeError('offset is not uint'); + if (offset + ext > length) + throw new RangeError('Trying to access beyond buffer length'); +} - assert.ok(offset < buffer.length, - 'Trying to read beyond buffer length'); - } - return buffer[offset]; +Buffer.prototype.readUInt8 = function(offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length); + return this[offset]; }; -function readUInt16(buffer, offset, isBigEndian, noAssert) { - var val = 0; - - - if (!noAssert) { - assert.ok(typeof (isBigEndian) === 'boolean', - 'missing or invalid endian'); - - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); - - assert.ok(offset + 1 < buffer.length, - 'Trying to read beyond buffer length'); - } +function readUInt16(buffer, offset, isBigEndian) { + var val = 0; if (isBigEndian) { val = buffer[offset] << 8; val |= buffer[offset + 1]; @@ -656,28 +649,24 @@ function readUInt16(buffer, offset, isBigEndian, noAssert) { return val; } + Buffer.prototype.readUInt16LE = function(offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length); return readUInt16(this, offset, false, noAssert); }; + Buffer.prototype.readUInt16BE = function(offset, noAssert) { + if (!noAssert) + checkOffset(offset, 2, this.length); return readUInt16(this, offset, true, noAssert); }; + function readUInt32(buffer, offset, isBigEndian, noAssert) { var val = 0; - if (!noAssert) { - assert.ok(typeof (isBigEndian) === 'boolean', - 'missing or invalid endian'); - - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); - - assert.ok(offset + 3 < buffer.length, - 'Trying to read beyond buffer length'); - } - if (isBigEndian) { val = buffer[offset + 1] << 16; val |= buffer[offset + 2] << 8; @@ -693,11 +682,17 @@ function readUInt32(buffer, offset, isBigEndian, noAssert) { return val; } + Buffer.prototype.readUInt32LE = function(offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length); return readUInt32(this, offset, false, noAssert); }; + Buffer.prototype.readUInt32BE = function(offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length); return readUInt32(this, offset, true, noAssert); }; @@ -747,113 +742,82 @@ Buffer.prototype.readUInt32BE = function(offset, noAssert) { * (0x007f + 1) * -1 * (0x0080) * -1 */ -Buffer.prototype.readInt8 = function(offset, noAssert) { - var buffer = this; - var neg; - if (!noAssert) { - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); - - assert.ok(offset < buffer.length, - 'Trying to read beyond buffer length'); - } - - neg = buffer[offset] & 0x80; - if (!neg) { - return (buffer[offset]); - } - - return ((0xff - buffer[offset] + 1) * -1); +Buffer.prototype.readInt8 = function(offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length); + if (!(this[offset] & 0x80)) + return (this[offset]); + return ((0xff - this[offset] + 1) * -1); }; -function readInt16(buffer, offset, isBigEndian, noAssert) { - var neg, val; - if (!noAssert) { - assert.ok(typeof (isBigEndian) === 'boolean', - 'missing or invalid endian'); +function readInt16(buffer, offset, isBigEndian) { + var val = readUInt16(buffer, offset, isBigEndian); - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); - - assert.ok(offset + 1 < buffer.length, - 'Trying to read beyond buffer length'); - } - - val = readUInt16(buffer, offset, isBigEndian, noAssert); - neg = val & 0x8000; - if (!neg) { + if (!(val & 0x8000)) return val; - } - return (0xffff - val + 1) * -1; } + Buffer.prototype.readInt16LE = function(offset, noAssert) { - return readInt16(this, offset, false, noAssert); + if (!noAssert) + checkOffset(offset, 2, this.length); + return readInt16(this, offset, false); }; + Buffer.prototype.readInt16BE = function(offset, noAssert) { - return readInt16(this, offset, true, noAssert); + if (!noAssert) + checkOffset(offset, 2, this.length); + return readInt16(this, offset, true); }; -function readInt32(buffer, offset, isBigEndian, noAssert) { - var neg, val; - - if (!noAssert) { - assert.ok(typeof (isBigEndian) === 'boolean', - 'missing or invalid endian'); - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); +function readInt32(buffer, offset, isBigEndian) { + var val = readUInt32(buffer, offset, isBigEndian); - assert.ok(offset + 3 < buffer.length, - 'Trying to read beyond buffer length'); - } - - val = readUInt32(buffer, offset, isBigEndian, noAssert); - neg = val & 0x80000000; - if (!neg) { + if (!(val & 0x80000000)) return (val); - } - return (0xffffffff - val + 1) * -1; } + Buffer.prototype.readInt32LE = function(offset, noAssert) { - return readInt32(this, offset, false, noAssert); + if (!noAssert) + checkOffset(offset, 2, this.length); + return readInt32(this, offset, false); }; + Buffer.prototype.readInt32BE = function(offset, noAssert) { - return readInt32(this, offset, true, noAssert); + if (!noAssert) + checkOffset(offset, 2, this.length); + return readInt32(this, offset, true); }; -function checkOffset(offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) - throw new RangeError('offset is not uint'); - if (offset + ext > length) - throw new RangeError('Trying to access beyond buffer length'); -} - Buffer.prototype.readFloatLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatLE(this.offset + offset, !!noAssert); }; + Buffer.prototype.readFloatBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatBE(this.offset + offset, !!noAssert); }; + Buffer.prototype.readDoubleLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); return this.parent.readDoubleLE(this.offset + offset, !!noAssert); }; + Buffer.prototype.readDoubleBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); @@ -861,63 +825,24 @@ Buffer.prototype.readDoubleBE = function(offset, noAssert) { }; -/* - * We have to make sure that the value is a valid integer. This means that it is - * non-negative. It has no fractional component and that it does not exceed the - * maximum allowed value. - * - * value The number to check for validity - * - * max The maximum value - */ -function verifuint(value, max) { - assert.ok(typeof (value) == 'number', - 'cannot write a non-number as a number'); - - assert.ok(value >= 0, - 'specified a negative value for writing an unsigned value'); - - assert.ok(value <= max, 'value is larger than maximum value for type'); - - assert.ok(Math.floor(value) === value, 'value has a fractional component'); +function checkInt(buffer, value, offset, ext, max, min) { + if ((value % 1) !== 0 || value > max || value < min) + throw TypeError("value is out of bounds"); + if ((offset % 1) !== 0 || offset < 0) + throw TypeError("offset is not uint"); + if (offset + ext > buffer.length || buffer.length + offset < 0) + throw RangeError("Trying to write outside buffer length"); } -Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { - var buffer = this; - - if (!noAssert) { - assert.ok(value !== undefined && value !== null, - 'missing value'); - - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); - - assert.ok(offset < buffer.length, - 'trying to write beyond buffer length'); - verifuint(value, 0xff); - } - - buffer[offset] = value; +Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { + if (!noAssert) + checkInt(this, value, offset, 1, 0xff, 0); + this[offset] = value; }; -function writeUInt16(buffer, value, offset, isBigEndian, noAssert) { - if (!noAssert) { - assert.ok(value !== undefined && value !== null, - 'missing value'); - - assert.ok(typeof (isBigEndian) === 'boolean', - 'missing or invalid endian'); - - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); - - assert.ok(offset + 1 < buffer.length, - 'trying to write beyond buffer length'); - - verifuint(value, 0xffff); - } +function writeUInt16(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value & 0xff00) >>> 8; buffer[offset + 1] = value & 0x00ff; @@ -927,31 +852,22 @@ function writeUInt16(buffer, value, offset, isBigEndian, noAssert) { } } + Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) { - writeUInt16(this, value, offset, false, noAssert); + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0); + writeUInt16(this, value, offset, false); }; + Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) { - writeUInt16(this, value, offset, true, noAssert); + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0); + writeUInt16(this, value, offset, true); }; -function writeUInt32(buffer, value, offset, isBigEndian, noAssert) { - if (!noAssert) { - assert.ok(value !== undefined && value !== null, - 'missing value'); - - assert.ok(typeof (isBigEndian) === 'boolean', - 'missing or invalid endian'); - - assert.ok(offset !== undefined && offset !== null, - 'missing offset'); - - assert.ok(offset + 3 < buffer.length, - 'trying to write beyond buffer length'); - - verifuint(value, 0xffffffff); - } +function writeUInt32(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value >>> 24) & 0xff; buffer[offset + 1] = (value >>> 16) & 0xff; @@ -965,12 +881,18 @@ function writeUInt32(buffer, value, offset, isBigEndian, noAssert) { } } + Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) { - writeUInt32(this, value, offset, false, noAssert); + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0); + writeUInt32(this, value, offset, false); }; + Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { - writeUInt32(this, value, offset, true, noAssert); + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0); + writeUInt32(this, value, offset, true); }; @@ -1011,92 +933,67 @@ Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { * hacky, but it should work and get the job done which is our goal here. */ -/* - * A series of checks to make sure we actually have a signed 32-bit number - */ -function verifsint(value, max, min) { - assert.ok(typeof (value) == 'number', - 'cannot write a non-number as a number'); - - assert.ok(value <= max, 'value larger than maximum allowed value'); - - assert.ok(value >= min, 'value smaller than minimum allowed value'); - - assert.ok(Math.floor(value) === value, 'value has a fractional component'); -} - Buffer.prototype.writeInt8 = function(value, offset, noAssert) { - var buffer = this; - - if (!noAssert) { - verifsint(value, 0x7f, -0x80); - } - - if (value >= 0) { - buffer.writeUInt8(value, offset, noAssert); - } else { - buffer.writeUInt8(0xff + value + 1, offset, noAssert); - } + if (!noAssert) + checkInt(this, value, offset, 1, 0x7f, -0x80); + if (value < 0) value = 0xff + value + 1; + this[offset] = value; }; -function writeInt16(buffer, value, offset, isBigEndian, noAssert) { - if (!noAssert) { - verifsint(value, 0x7fff, -0x8000); - } - - if (value >= 0) { - writeUInt16(buffer, value, offset, isBigEndian, noAssert); - } else { - writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert); - } -} Buffer.prototype.writeInt16LE = function(value, offset, noAssert) { - writeInt16(this, value, offset, false, noAssert); + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (value < 0) value = 0xffff + value + 1; + writeUInt16(this, value, offset, false); }; + Buffer.prototype.writeInt16BE = function(value, offset, noAssert) { - writeInt16(this, value, offset, true, noAssert); + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (value < 0) value = 0xffff + value + 1; + writeUInt16(this, value, offset, true); }; -function writeInt32(buffer, value, offset, isBigEndian, noAssert) { - if (!noAssert) { - verifsint(value, 0x7fffffff, -0x80000000); - } - - if (value >= 0) { - writeUInt32(buffer, value, offset, isBigEndian, noAssert); - } else { - writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert); - } -} Buffer.prototype.writeInt32LE = function(value, offset, noAssert) { - writeInt32(this, value, offset, false, noAssert); + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (value < 0) value = 0xffffffff + value + 1; + writeUInt32(this, value, offset, false); }; + Buffer.prototype.writeInt32BE = function(value, offset, noAssert) { - writeInt32(this, value, offset, true, noAssert); + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (value < 0) value = 0xffffffff + value + 1; + writeUInt32(this, value, offset, true); }; + Buffer.prototype.writeFloatLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatLE(value, this.offset + offset, !!noAssert); }; + Buffer.prototype.writeFloatBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatBE(value, this.offset + offset, !!noAssert); }; + Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); this.parent.writeDoubleLE(value, this.offset + offset, !!noAssert); }; + Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length);