Skip to content
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: validate arg types #23840

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 15 additions & 32 deletions lib/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const {
ERR_NO_LONGER_SUPPORTED,
ERR_UNKNOWN_ENCODING
} = require('internal/errors').codes;
const { validateString } = require('internal/validators');
const { validateString, validateUint32 } = require('internal/validators');

const internalBuffer = require('internal/buffer');

Expand Down Expand Up @@ -624,10 +624,16 @@ function stringSlice(buf, encoding, start, end) {
throw new ERR_UNKNOWN_ENCODING(encoding);
}

Buffer.prototype.copy =
function copy(target, targetStart, sourceStart, sourceEnd) {
return _copy(this, target, targetStart, sourceStart, sourceEnd);
};
Buffer.prototype.copy = function(target, targetStart, sourceStart, sourceEnd) {
if (!isUint8Array(target)) {
throw new ERR_INVALID_ARG_TYPE(
'target', ['Buffer', 'Uint8Array'], target);
}
targetStart = validateUint32(targetStart, 'targetStart');
sourceStart = validateUint32(sourceStart, 'sourceStart');
sourceEnd = validateUint32(sourceEnd, 'sourceEnd') || this.length;
return _copy(this, target, targetStart, sourceStart, sourceEnd);
};

// No need to verify that "buf.length <= MAX_UINT32" since it's a read-only
// property of a typed array.
Expand Down Expand Up @@ -694,33 +700,10 @@ Buffer.prototype.compare = function compare(target,
if (arguments.length === 1)
return _compare(this, target);

if (targetStart === undefined)
targetStart = 0;
else if (targetStart < 0)
throw new ERR_OUT_OF_RANGE('targetStart', '>= 0', targetStart);
else
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;

if (sourceStart === undefined)
sourceStart = 0;
else if (sourceStart < 0)
throw new ERR_OUT_OF_RANGE('sourceStart', '>= 0', sourceStart);
else
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;
targetStart = validateUint32(targetStart, 'targetStart');
targetEnd = validateUint32(targetEnd, 'targetEnd') || target.length;
sourceStart = validateUint32(sourceStart, 'sourceStart');
sourceEnd = validateUint32(sourceEnd, 'sourceEnd') || this.length;

if (sourceStart >= sourceEnd)
return (targetStart >= targetEnd ? 0 : -1);
Expand Down
3 changes: 2 additions & 1 deletion test/parallel/test-buffer-alloc.js
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,8 @@ common.expectsError(
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
message: 'argument must be a buffer'
message: 'The "target" argument must be one of type Buffer or ' +
'Uint8Array. Received type undefined'
});

assert.throws(() => Buffer.from(), {
Expand Down
74 changes: 0 additions & 74 deletions test/parallel/test-buffer-compare-offset.js

This file was deleted.

125 changes: 125 additions & 0 deletions test/parallel/test-buffer-compare.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,128 @@ common.expectsError(() => Buffer.alloc(1).compare('abc'), {
message: 'The "target" argument must be one of ' +
'type Buffer or Uint8Array. Received type string'
});


// Test compare with offset
{
const a = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
const b = Buffer.from([5, 6, 7, 8, 9, 0, 1, 2, 3, 4]);

assert.strictEqual(a.compare(b), -1);

// Equivalent to a.compare(b).
assert.strictEqual(a.compare(b, 0), -1);
assert.strictEqual(a.compare(b, '0'), -1);
assert.strictEqual(a.compare(b, undefined), -1);

// Equivalent to a.compare(b).
assert.strictEqual(a.compare(b, 0, undefined, 0), -1);

// Zero-length target, return 1
assert.strictEqual(a.compare(b, 0, 0, 0), 1);
assert.strictEqual(a.compare(b, '0', '0', '0'), 1);

// Equivalent to Buffer.compare(a, b.slice(6, 10))
assert.strictEqual(a.compare(b, 6, 10), 1);

// Zero-length source, return -1
assert.strictEqual(a.compare(b, 6, 10, 0, 0), -1);

// Zero-length source and target, return 0
assert.strictEqual(a.compare(b, 0, 0, 0, 0), 0);
assert.strictEqual(a.compare(b, 1, 1, 2, 2), 0);

// Equivalent to Buffer.compare(a.slice(4), b.slice(0, 5))
assert.strictEqual(a.compare(b, 0, 5, 4), 1);

// Equivalent to Buffer.compare(a.slice(1), b.slice(5))
assert.strictEqual(a.compare(b, 5, undefined, 1), 1);

// Equivalent to Buffer.compare(a.slice(2), b.slice(2, 4))
assert.strictEqual(a.compare(b, 2, 4, 2), -1);

// Equivalent to Buffer.compare(a.slice(4), b.slice(0, 7))
assert.strictEqual(a.compare(b, 0, 7, 4), -1);

// Equivalent to Buffer.compare(a.slice(4, 6), b.slice(0, 7));
assert.strictEqual(a.compare(b, 0, 7, 4, 6), -1);

// zero length target
assert.strictEqual(a.compare(b, 0, null), 1);

// coerces to targetEnd == 5
assert.strictEqual(a.compare(b, 0, { valueOf: () => 5 }), -1);

// zero length target
assert.strictEqual(a.compare(b, Infinity, -Infinity), 1);

// zero length target because default for targetEnd <= targetSource
assert.strictEqual(a.compare(b, '0xff'), 1);

const oor = common.expectsError({ code: 'ERR_OUT_OF_RANGE' }, 7);

assert.throws(() => a.compare(b, 0, 100, 0), oor);
assert.throws(() => a.compare(b, 0, 1, 0, 100), oor);
assert.throws(() => a.compare(b, -1), oor);
assert.throws(() => a.compare(b, 0, '0xff'), oor);
assert.throws(() => a.compare(b, 0, Infinity), oor);
assert.throws(() => a.compare(b, 0, 1, -1), oor);
assert.throws(() => a.compare(b, -Infinity, Infinity), oor);
common.expectsError(() => a.compare(), {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
message: 'The "target" argument must be one of ' +
'type Buffer or Uint8Array. Received type undefined'
});

// Validate arg type checking.
// Refs: https://github.com/nodejs/node/issues/23668
{
const expected = {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
}

common.expectsError(
() => b.compare(c, '1'),
expected
);
common.expectsError(
() => b.compare(c, 0, '1'),
expected
);
common.expectsError(
() => b.compare(c, 0, 0, '1'),
expected
);
common.expectsError(
() => b.compare(c, 0, 0, 0, '1'),
expected
);
}

// Extra! Validate arg range checking.
// Refs: https://github.com/nodejs/node/issues/23668
{
const expected = {
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
}
common.expectsError(
() => b.copy(c, -1),
expected
);
common.expectsError(
() => b.copy(c, 0, -1),
expected
);
common.expectsError(
() => b.copy(c, 0, 0, -1),
expected
);
common.expectsError(
() => b.copy(c, 0, 0, 0, -1),
expected
);
}
}
47 changes: 46 additions & 1 deletion test/parallel/test-buffer-copy.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

require('../common');
const common = require('../common');
const assert = require('assert');

const b = Buffer.allocUnsafe(1024);
Expand Down Expand Up @@ -144,3 +144,48 @@ assert.strictEqual(b.copy(c, 512, 0, 10), 0);
assert.strictEqual(c[i], e[i]);
}
}


// Validate arg type checking.
// Refs: https://github.com/nodejs/node/issues/23668
{
const expected = {
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
}

common.expectsError(
() => b.copy(c, '1'),
expected
);
common.expectsError(
() => b.copy(c, 0, '1'),
expected
);
common.expectsError(
() => b.copy(c, 0, 0, '1'),
);
}


// Validate arg range checking.
// Refs: https://github.com/nodejs/node/issues/23668
{
const expected = {
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
}

common.expectsError(
() => b.copy(c, -1),
expected
);
common.expectsError(
() => b.copy(c, 0, -1),
expected
);
common.expectsError(
() => b.copy(c, 0, 0, -1),
expected
);
}