util: fix out of bounds indices in util.inspect

This fixes a issue brought up in #15288.

PR-URL: https://github.com/nodejs/node/pull/14881
Refs: https://github.com/nodejs/node/issues/15288
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
Ruben Bridgewater 2017-09-09 03:32:08 -03:00
parent f9ad23dc91
commit bac313b086
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
2 changed files with 39 additions and 6 deletions

View File

@ -652,6 +652,9 @@ function formatSpecialArray(ctx, value, recurseTimes, keys, maxLength, valLen) {
if (visibleLength === maxLength) if (visibleLength === maxLength)
break; break;
const index = +key; const index = +key;
// Arrays can only have up to 2^32 - 1 entries
if (index > 2 ** 32 - 2)
break;
if (i !== index) { if (i !== index) {
if (!numberRegExp.test(key)) if (!numberRegExp.test(key))
break; break;
@ -674,6 +677,8 @@ function formatSpecialArray(ctx, value, recurseTimes, keys, maxLength, valLen) {
const message = `<${len} empty item${ending}>`; const message = `<${len} empty item${ending}>`;
output.push(ctx.stylize(message, 'undefined')); output.push(ctx.stylize(message, 'undefined'));
i = valLen; i = valLen;
if (keyLen === 0)
return output;
} }
const remaining = valLen - i; const remaining = valLen - i;
if (remaining > 0) { if (remaining > 0) {
@ -687,13 +692,18 @@ function formatSpecialArray(ctx, value, recurseTimes, keys, maxLength, valLen) {
// The array is not sparse // The array is not sparse
for (i = valLen; i < keyLen; i++) for (i = valLen; i < keyLen; i++)
output.push(formatProperty(ctx, value, recurseTimes, keys[i], 2)); output.push(formatProperty(ctx, value, recurseTimes, keys[i], 2));
} else if (keyLen !== 0 && keys[keyLen - 1] !== `${valLen - 1}`) { } else if (keys[keyLen - 1] !== `${valLen - 1}`) {
for (const key of keys) { const extra = [];
// Skip regular indices // Only handle special keys
if (!numberRegExp.test(key)) { var key;
output.push(formatProperty(ctx, value, recurseTimes, key, 2)); for (i = keys.length - 1; i >= 0; i--) {
} key = keys[i];
if (numberRegExp.test(key) && +key < 2 ** 32 - 1)
break;
extra.push(formatProperty(ctx, value, recurseTimes, key, 2));
} }
for (i = extra.length - 1; i >= 0; i--)
output.push(extra[i]);
} }
return output; return output;
} }

View File

@ -361,6 +361,29 @@ assert.strictEqual(
assert.strictEqual(util.inspect(arr3), "[ '-1': -1 ]"); assert.strictEqual(util.inspect(arr3), "[ '-1': -1 ]");
} }
// Indices out of bounds
{
const arr = [];
arr[2 ** 32] = true; // not a valid array index
assert.strictEqual(util.inspect(arr), "[ '4294967296': true ]");
arr[0] = true;
arr[10] = true;
assert.strictEqual(util.inspect(arr),
"[ true, <9 empty items>, true, '4294967296': true ]");
arr[2 ** 32 - 2] = true;
arr[2 ** 32 - 1] = true;
arr[2 ** 32 + 1] = true;
delete arr[0];
delete arr[10];
assert.strictEqual(util.inspect(arr),
['[ <4294967294 empty items>,',
'true,',
"'4294967296': true,",
"'4294967295': true,",
"'4294967297': true ]"
].join('\n '));
}
// Function with properties // Function with properties
{ {
const value = () => {}; const value = () => {};