diff --git a/lib/buffer.js b/lib/buffer.js index d9c64f27cf3e..2d900dff1746 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -1109,11 +1109,21 @@ Buffer.prototype.compare = function compare(target, // - buffer - a Buffer to search // - val - a string, Buffer, or number // - byteOffset - an index into `buffer`; will be clamped to an int32 -// - end - absolute exclusive end of the search range +// - end - absolute exclusive end of the search range; will be clamped to +// [0, buffer.byteLength] // - encoding - an optional encoding, relevant if val is a string // - dir - true for indexOf, false for lastIndexOf function bidirectionalIndexOf(buffer, val, byteOffset, end, encoding, dir) { validateBuffer(buffer); + validateNumber(end, 'end'); + + // The binding converts `end` to an int64, so keep NaN, Infinity and other + // values outside the buffer from reaching it. NaN selects an empty range. + if (end > buffer.byteLength) { + end = buffer.byteLength; + } else if (!(end >= 0)) { + end = 0; + } if (typeof byteOffset === 'string') { encoding = byteOffset; diff --git a/test/parallel/test-buffer-indexof.js b/test/parallel/test-buffer-indexof.js index f23c84bdf2ea..6ca10253a2ff 100644 --- a/test/parallel/test-buffer-indexof.js +++ b/test/parallel/test-buffer-indexof.js @@ -758,3 +758,43 @@ assert.strictEqual(reallyLong.lastIndexOf(pattern), 0); assert.strictEqual(buf.lastIndexOf('', 5, 3), 3); assert.strictEqual(buf.lastIndexOf(Buffer.from(''), 5, 3), 3); } + +{ + const buf = Buffer.from('abcabc'); + + // Non-number end values used to reach a native CHECK and abort the process. + assert.throws(() => buf.indexOf('a', 0, null), { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: 'The "end" argument must be of type number. Received null', + }); + for (const end of [null, true, {}, [], 1n, Symbol('end')]) { + for (const method of ['indexOf', 'lastIndexOf', 'includes']) { + for (const value of ['a', 0x61, Buffer.from('a')]) { + assert.throws(() => buf[method](value, 0, end), { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + }); + } + } + } + + // End values outside the int64 range are clamped to the buffer length. + assert.strictEqual(buf.indexOf('a', 0, Infinity), 0); + assert.strictEqual(buf.indexOf(0x61, 0, Infinity), 0); + assert.strictEqual(buf.indexOf(Buffer.from('a'), 0, Infinity), 0); + assert.strictEqual(buf.indexOf('a', 0, 1e20), 0); + assert.strictEqual(buf.indexOf(0x61, 0, 1e20), 0); + assert.strictEqual(buf.lastIndexOf('a', 5, Infinity), 3); + assert.strictEqual(buf.lastIndexOf(0x61, 5, Infinity), 3); + assert.strictEqual(buf.lastIndexOf(Buffer.from('a'), 5, Infinity), 3); + assert.strictEqual(buf.includes('c', 0, Infinity), true); + + // -Infinity and NaN select an empty range. + assert.strictEqual(buf.indexOf('a', 0, -Infinity), -1); + assert.strictEqual(buf.indexOf('a', 0, NaN), -1); + assert.strictEqual(buf.indexOf(0x61, 0, NaN), -1); + assert.strictEqual(buf.indexOf(Buffer.from('a'), 0, NaN), -1); + assert.strictEqual(buf.lastIndexOf('a', 5, NaN), -1); + assert.strictEqual(buf.includes('a', 0, NaN), false); +}