buffer: use stricter range checks

This validates the input to make sure the arguments do not overflow.
Before, if the input would overflow, it would cause the write to be
performt in the wrong spot / result in unexpected behavior.
Instead, just use a strict number validation.

PR-URL: https://github.com/nodejs/node/pull/27045
Fixes: https://github.com/nodejs/node/issues/27043
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Ruben Bridgewater committed 2019-04-15 17:21:34 +02:00
1 parent 2fed83dee8
commit 693401d0dd
7 files changed
+98 -102

No files matched your search

+30 -43
View File
@@ -65,17 +65,18 @@ const {
const {
codes: {
ERR_BUFFER_OUT_OF_BOUNDS,
ERR_OUT_OF_RANGE,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_INVALID_BUFFER_SIZE,
ERR_INVALID_OPT_VALUE,
ERR_NO_LONGER_SUPPORTED,
ERR_UNKNOWN_ENCODING
},
hideStackFrames
} = require('internal/errors');
const { validateString } = require('internal/validators');
const {
validateInt32,
validateString
} = require('internal/validators');
const {
FastBuffer,
@@ -445,7 +446,7 @@ Buffer.concat = function concat(list, length) {
}
}
} else {
length = length >>> 0;
validateInt32(length, 'length', 0);
}
const buffer = Buffer.allocUnsafe(length);
@@ -700,35 +701,27 @@ Buffer.prototype.compare = function compare(target,
if (targetStart === undefined)
targetStart = 0;
else if (targetStart < 0)
throw new ERR_OUT_OF_RANGE('targetStart', '>= 0', targetStart);
else
targetStart >>>= 0;
validateInt32(targetStart, 'targetStart', 0);
if (targetEnd === undefined)
targetEnd = target.length;
else if (targetEnd > target.length)
throw new ERR_OUT_OF_RANGE('targetEnd', `<= ${target.length}`, targetEnd);
else
targetEnd >>>= 0;
validateInt32(targetEnd, 'targetEnd', 0, target.length);
if (sourceStart === undefined)
sourceStart = 0;
else if (sourceStart < 0)
throw new ERR_OUT_OF_RANGE('sourceStart', '>= 0', sourceStart);
else
sourceStart >>>= 0;
validateInt32(sourceStart, 'sourceStart', 0);
if (sourceEnd === undefined)
sourceEnd = this.length;
else if (sourceEnd > this.length)
throw new ERR_OUT_OF_RANGE('sourceEnd', `<= ${this.length}`, sourceEnd);
else
sourceEnd >>>= 0;
validateInt32(sourceEnd, 'sourceEnd', 0, this.length);
if (sourceStart >= sourceEnd)
return (targetStart >= targetEnd ? 0 : -1);
else if (targetStart >= targetEnd)
if (targetStart >= targetEnd)
return 1;
return compareOffset(this, target, targetStart, sourceStart, targetEnd,
@@ -867,17 +860,13 @@ function _fill(buf, value, offset, end, encoding) {
offset = 0;
end = buf.length;
} else {
validateInt32(offset, 'offset', 0);
// Invalid ranges are not set to a default, so can range check early.
if (offset < 0)
throw new ERR_OUT_OF_RANGE('offset', '>= 0', offset);
if (end === undefined) {
end = buf.length;
} else {
if (end > buf.length || end < 0)
throw new ERR_OUT_OF_RANGE('end', `>= 0 and <= ${buf.length}`, end);
end = end >>> 0;
validateInt32(end, 'end', 0, buf.length);
}
offset = offset >>> 0;
if (offset >= end)
return buf;
}
@@ -896,39 +885,37 @@ Buffer.prototype.write = function write(string, offset, length, encoding) {
// Buffer#write(string);
if (offset === undefined) {
return this.utf8Write(string, 0, this.length);
}
// Buffer#write(string, encoding)
} else if (length === undefined && typeof offset === 'string') {
if (length === undefined && typeof offset === 'string') {
encoding = offset;
length = this.length;
offset = 0;
// Buffer#write(string, offset[, length][, encoding])
} else if (isFinite(offset)) {
offset = offset >>> 0;
if (isFinite(length)) {
length = length >>> 0;
} else {
if (offset === undefined) {
offset = 0;
} else {
encoding = length;
length = undefined;
validateInt32(offset, 'offset', 0, this.length);
}
const remaining = this.length - offset;
if (length === undefined || length > remaining)
length = remaining;
if (string.length > 0 && (length < 0 || offset < 0))
throw new ERR_BUFFER_OUT_OF_BOUNDS();
} else {
// If someone is still calling the obsolete form of write(), tell them.
// we don't want eg buf.write("foo", "utf8", 10) to silently turn into
// buf.write("foo", "utf8"), so we can't ignore extra args
throw new ERR_NO_LONGER_SUPPORTED(
'Buffer.write(string, encoding, offset[, length])'
);
if (length === undefined) {
length = remaining;
} else if (typeof length === 'string') {
encoding = length;
length = remaining;
} else {
validateInt32(length, 'length', 0, this.length);
if (length > remaining)
length = remaining;
}
}
if (!encoding) return this.utf8Write(string, offset, length);
if (!encoding)
return this.utf8Write(string, offset, length);
encoding += '';
switch (encoding.length) {