-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
buffer: fix segfaults when this
is not a Buffer.
#1486
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -300,8 +300,28 @@ function byteLength(string, encoding) { | |
|
||
Buffer.byteLength = byteLength; | ||
|
||
|
||
Buffer.prototype.copy = function(target, targetStart, sourceStart, sourceEnd) { | ||
if (!(this instanceof Buffer)) | ||
throw new TypeError('this is not an instance of Buffer'); | ||
|
||
if (!(target instanceof Buffer)) | ||
throw new TypeError('target is not an instance of Buffer'); | ||
|
||
return binding.copy(this, target, targetStart, sourceStart, sourceEnd); | ||
}; | ||
|
||
// toString(encoding, start=0, end=buffer.length) | ||
Buffer.prototype.toString = function(encoding, start, end) { | ||
if (!(this instanceof Buffer)) { | ||
// If no arguments, then this is probably an implicit coercion, and we | ||
// shouldn't throw. | ||
if (arguments.length === 0) | ||
return Object.prototype.toString.call(this); | ||
else | ||
throw new TypeError('this is not an instance of Buffer'); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: no need for the |
||
|
||
var loweredCase = false; | ||
|
||
start = start >>> 0; | ||
|
@@ -315,26 +335,26 @@ Buffer.prototype.toString = function(encoding, start, end) { | |
while (true) { | ||
switch (encoding) { | ||
case 'hex': | ||
return this.hexSlice(start, end); | ||
return binding.hexSlice(this, start, end); | ||
|
||
case 'utf8': | ||
case 'utf-8': | ||
return this.utf8Slice(start, end); | ||
return binding.utf8Slice(this, start, end); | ||
|
||
case 'ascii': | ||
return this.asciiSlice(start, end); | ||
return binding.asciiSlice(this, start, end); | ||
|
||
case 'binary': | ||
return this.binarySlice(start, end); | ||
return binding.binarySlice(this, start, end); | ||
|
||
case 'base64': | ||
return this.base64Slice(start, end); | ||
return binding.base64Slice(this, start, end); | ||
|
||
case 'ucs2': | ||
case 'ucs-2': | ||
case 'utf16le': | ||
case 'utf-16le': | ||
return this.ucs2Slice(start, end); | ||
return binding.ucs2Slice(this, start, end); | ||
|
||
default: | ||
if (loweredCase) | ||
|
@@ -345,6 +365,30 @@ Buffer.prototype.toString = function(encoding, start, end) { | |
} | ||
}; | ||
|
||
Buffer.prototype.asciiSlice = function(start, end) { | ||
return this.toString('ascii', start, end); | ||
}; | ||
|
||
Buffer.prototype.base64Slice = function(start, end) { | ||
return this.toString('base64', start, end); | ||
}; | ||
|
||
Buffer.prototype.binarySlice = function(start, end) { | ||
return this.toString('binary', start, end); | ||
}; | ||
|
||
Buffer.prototype.hexSlice = function(start, end) { | ||
return this.toString('hex', start, end); | ||
}; | ||
|
||
Buffer.prototype.ucs2Slice = function(start, end) { | ||
return this.toString('ucs2', start, end); | ||
}; | ||
|
||
Buffer.prototype.utf8Slice = function(start, end) { | ||
return this.toString('utf8', start, end); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this makes my heart hurt. i used to use these as a more performant way of doing operations. though they are also no loner documented (though IIRC they once were). guess I'll have to switch to using |
||
}; | ||
|
||
|
||
Buffer.prototype.equals = function equals(b) { | ||
if (!(b instanceof Buffer)) | ||
|
@@ -371,6 +415,9 @@ Buffer.prototype.inspect = function inspect() { | |
|
||
|
||
Buffer.prototype.compare = function compare(b) { | ||
if (!(this instanceof Buffer)) | ||
throw new TypeError('this is not an instance of Buffer'); | ||
|
||
if (!(b instanceof Buffer)) | ||
throw new TypeError('Argument must be a Buffer'); | ||
|
||
|
@@ -382,6 +429,9 @@ Buffer.prototype.compare = function compare(b) { | |
|
||
|
||
Buffer.prototype.indexOf = function indexOf(val, byteOffset) { | ||
if (!(this instanceof Buffer)) | ||
throw new TypeError('this is not an instance of Buffer'); | ||
|
||
if (byteOffset > 0x7fffffff) | ||
byteOffset = 0x7fffffff; | ||
else if (byteOffset < -0x80000000) | ||
|
@@ -400,6 +450,9 @@ Buffer.prototype.indexOf = function indexOf(val, byteOffset) { | |
|
||
|
||
Buffer.prototype.fill = function fill(val, start, end) { | ||
if (!(this instanceof Buffer)) | ||
throw new TypeError('this is not an instance of Buffer'); | ||
|
||
start = start >> 0; | ||
end = (end === undefined) ? this.length : end >> 0; | ||
|
||
|
@@ -446,6 +499,12 @@ var writeWarned = false; | |
const writeMsg = '.write(string, encoding, offset, length) is deprecated.' + | ||
' Use write(string[, offset[, length]][, encoding]) instead.'; | ||
Buffer.prototype.write = function(string, offset, length, encoding) { | ||
if (!(this instanceof Buffer)) | ||
throw new TypeError('this is not an instance of Buffer'); | ||
|
||
if (typeof string !== 'string') | ||
throw new TypeError('Argument must be a string'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't agree with this. primitives like strings should always be coerced, IMO. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a throw ported from C++, but of course there is no problem with coercing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gah! hate that we have such inconsistency in how we handle types. thanks for clarifying. |
||
|
||
// Buffer#write(string); | ||
if (offset === undefined) { | ||
encoding = 'utf8'; | ||
|
@@ -502,27 +561,29 @@ Buffer.prototype.write = function(string, offset, length, encoding) { | |
for (;;) { | ||
switch (encoding) { | ||
case 'hex': | ||
return this.hexWrite(string, offset, length); | ||
if (string.length % 2 !== 0) | ||
throw new TypeError('Invalid hex string'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all this extra throwing needs to be documented, if it's not already. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. okay, maybe not all of it (like checking There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that is not an extra throw, it is an existing throw ported from C++ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks. |
||
return binding.hexWrite(this, string, offset, length); | ||
|
||
case 'utf8': | ||
case 'utf-8': | ||
return this.utf8Write(string, offset, length); | ||
return binding.utf8Write(this, string, offset, length); | ||
|
||
case 'ascii': | ||
return this.asciiWrite(string, offset, length); | ||
return binding.asciiWrite(this, string, offset, length); | ||
|
||
case 'binary': | ||
return this.binaryWrite(string, offset, length); | ||
return binding.binaryWrite(this, string, offset, length); | ||
|
||
case 'base64': | ||
// Warning: maxLength not taken into account in base64Write | ||
return this.base64Write(string, offset, length); | ||
return binding.base64Write(this, string, offset, length); | ||
|
||
case 'ucs2': | ||
case 'ucs-2': | ||
case 'utf16le': | ||
case 'utf-16le': | ||
return this.ucs2Write(string, offset, length); | ||
return binding.ucs2Write(this, string, offset, length); | ||
|
||
default: | ||
if (loweredCase) | ||
|
@@ -533,6 +594,30 @@ Buffer.prototype.write = function(string, offset, length, encoding) { | |
} | ||
}; | ||
|
||
Buffer.prototype.asciiWrite = function(string, offset, length) { | ||
return this.write(string, offset, length, 'ascii'); | ||
}; | ||
|
||
Buffer.prototype.base64Write = function(string, offset, length) { | ||
return this.write(string, offset, length, 'base64'); | ||
}; | ||
|
||
Buffer.prototype.binaryWrite = function(string, offset, length) { | ||
return this.write(string, offset, length, 'binary'); | ||
}; | ||
|
||
Buffer.prototype.hexWrite = function(string, offset, length) { | ||
return this.write(string, offset, length, 'hex'); | ||
}; | ||
|
||
Buffer.prototype.ucs2Write = function(string, offset, length) { | ||
return this.write(string, offset, length, 'ucs2'); | ||
}; | ||
|
||
Buffer.prototype.utf8Write = function(string, offset, length) { | ||
return this.write(string, offset, length, 'utf8'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we might as well deprecate these calls if they're just being sent back to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto on deprecating the |
||
}; | ||
|
||
|
||
Buffer.prototype.toJSON = function() { | ||
return { | ||
|
@@ -545,6 +630,9 @@ Buffer.prototype.toJSON = function() { | |
// TODO(trevnorris): currently works like Array.prototype.slice(), which | ||
// doesn't follow the new standard for throwing on out of range indexes. | ||
Buffer.prototype.slice = function(start, end) { | ||
if (!(this instanceof Buffer)) | ||
throw new TypeError('this is not an instance of Buffer'); | ||
|
||
var len = this.length; | ||
start = ~~start; | ||
end = end === undefined ? len : ~~end; | ||
|
@@ -578,7 +666,9 @@ Buffer.prototype.slice = function(start, end) { | |
}; | ||
|
||
|
||
function checkOffset(offset, ext, length) { | ||
function checkOffset(buffer, offset, ext, length) { | ||
if (!(buffer instanceof Buffer)) | ||
throw new TypeError('this is not an instance of Buffer'); | ||
if (offset + ext > length) | ||
throw new RangeError('index out of range'); | ||
} | ||
|
@@ -588,7 +678,7 @@ Buffer.prototype.readUIntLE = function(offset, byteLength, noAssert) { | |
offset = offset >>> 0; | ||
byteLength = byteLength >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, byteLength, this.length); | ||
checkOffset(this, offset, byteLength, this.length); | ||
|
||
var val = this[offset]; | ||
var mul = 1; | ||
|
@@ -604,7 +694,7 @@ Buffer.prototype.readUIntBE = function(offset, byteLength, noAssert) { | |
offset = offset >>> 0; | ||
byteLength = byteLength >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, byteLength, this.length); | ||
checkOffset(this, offset, byteLength, this.length); | ||
|
||
var val = this[offset + --byteLength]; | ||
var mul = 1; | ||
|
@@ -618,31 +708,31 @@ Buffer.prototype.readUIntBE = function(offset, byteLength, noAssert) { | |
Buffer.prototype.readUInt8 = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 1, this.length); | ||
checkOffset(this, offset, 1, this.length); | ||
return this[offset]; | ||
}; | ||
|
||
|
||
Buffer.prototype.readUInt16LE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 2, this.length); | ||
checkOffset(this, offset, 2, this.length); | ||
return this[offset] | (this[offset + 1] << 8); | ||
}; | ||
|
||
|
||
Buffer.prototype.readUInt16BE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 2, this.length); | ||
checkOffset(this, offset, 2, this.length); | ||
return (this[offset] << 8) | this[offset + 1]; | ||
}; | ||
|
||
|
||
Buffer.prototype.readUInt32LE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 4, this.length); | ||
checkOffset(this, offset, 4, this.length); | ||
|
||
return ((this[offset]) | | ||
(this[offset + 1] << 8) | | ||
|
@@ -654,7 +744,7 @@ Buffer.prototype.readUInt32LE = function(offset, noAssert) { | |
Buffer.prototype.readUInt32BE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 4, this.length); | ||
checkOffset(this, offset, 4, this.length); | ||
|
||
return (this[offset] * 0x1000000) + | ||
((this[offset + 1] << 16) | | ||
|
@@ -667,7 +757,7 @@ Buffer.prototype.readIntLE = function(offset, byteLength, noAssert) { | |
offset = offset >>> 0; | ||
byteLength = byteLength >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, byteLength, this.length); | ||
checkOffset(this, offset, byteLength, this.length); | ||
|
||
var val = this[offset]; | ||
var mul = 1; | ||
|
@@ -687,7 +777,7 @@ Buffer.prototype.readIntBE = function(offset, byteLength, noAssert) { | |
offset = offset >>> 0; | ||
byteLength = byteLength >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, byteLength, this.length); | ||
checkOffset(this, offset, byteLength, this.length); | ||
|
||
var i = byteLength; | ||
var mul = 1; | ||
|
@@ -706,7 +796,7 @@ Buffer.prototype.readIntBE = function(offset, byteLength, noAssert) { | |
Buffer.prototype.readInt8 = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 1, this.length); | ||
checkOffset(this, offset, 1, this.length); | ||
var val = this[offset]; | ||
return !(val & 0x80) ? val : (0xff - val + 1) * -1; | ||
}; | ||
|
@@ -715,7 +805,7 @@ Buffer.prototype.readInt8 = function(offset, noAssert) { | |
Buffer.prototype.readInt16LE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 2, this.length); | ||
checkOffset(this, offset, 2, this.length); | ||
var val = this[offset] | (this[offset + 1] << 8); | ||
return (val & 0x8000) ? val | 0xFFFF0000 : val; | ||
}; | ||
|
@@ -724,7 +814,7 @@ Buffer.prototype.readInt16LE = function(offset, noAssert) { | |
Buffer.prototype.readInt16BE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 2, this.length); | ||
checkOffset(this, offset, 2, this.length); | ||
var val = this[offset + 1] | (this[offset] << 8); | ||
return (val & 0x8000) ? val | 0xFFFF0000 : val; | ||
}; | ||
|
@@ -733,7 +823,7 @@ Buffer.prototype.readInt16BE = function(offset, noAssert) { | |
Buffer.prototype.readInt32LE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 4, this.length); | ||
checkOffset(this, offset, 4, this.length); | ||
|
||
return (this[offset]) | | ||
(this[offset + 1] << 8) | | ||
|
@@ -745,7 +835,7 @@ Buffer.prototype.readInt32LE = function(offset, noAssert) { | |
Buffer.prototype.readInt32BE = function(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 4, this.length); | ||
checkOffset(this, offset, 4, this.length); | ||
|
||
return (this[offset] << 24) | | ||
(this[offset + 1] << 16) | | ||
|
@@ -757,31 +847,31 @@ Buffer.prototype.readInt32BE = function(offset, noAssert) { | |
Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 4, this.length); | ||
checkOffset(this, offset, 4, this.length); | ||
return binding.readFloatLE(this, offset); | ||
}; | ||
|
||
|
||
Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 4, this.length); | ||
checkOffset(this, offset, 4, this.length); | ||
return binding.readFloatBE(this, offset); | ||
}; | ||
|
||
|
||
Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 8, this.length); | ||
checkOffset(this, offset, 8, this.length); | ||
return binding.readDoubleLE(this, offset); | ||
}; | ||
|
||
|
||
Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) { | ||
offset = offset >>> 0; | ||
if (!noAssert) | ||
checkOffset(offset, 8, this.length); | ||
checkOffset(this, offset, 8, this.length); | ||
return binding.readDoubleBE(this, offset); | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though this case is insane, it inevitably will break someone in the wild. Because of that this is a sem-minor patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which part will break? if
this
is not a Buffer the process will crashThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hehe. okay true enough. in that case I'd consider this a bug fix patch. :)