buffer: fix indexOf for empty searches
Make searches for empty subsequences do exactly what `String.prototype.indexOf()` does. Fixes: https://github.com/nodejs/node/issues/13023 PR-URL: https://github.com/nodejs/node/pull/13024 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
This commit is contained in:
parent
5a948f6f64
commit
28ddac2ec2
@ -1340,6 +1340,10 @@ console.log(b.indexOf('b', null));
|
|||||||
console.log(b.indexOf('b', []));
|
console.log(b.indexOf('b', []));
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If `value` is an empty string or empty `Buffer` and `byteOffset` is less
|
||||||
|
than `buf.length`, `byteOffset` will be returned. If `value` is empty and
|
||||||
|
`byteOffset` is at least `buf.length`, `buf.length` will be returned.
|
||||||
|
|
||||||
### buf.keys()
|
### buf.keys()
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v1.1.0
|
added: v1.1.0
|
||||||
@ -1450,6 +1454,8 @@ console.log(b.lastIndexOf('b', null));
|
|||||||
console.log(b.lastIndexOf('b', []));
|
console.log(b.lastIndexOf('b', []));
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If `value` is an empty string or empty `Buffer`, `byteOffset` will be returned.
|
||||||
|
|
||||||
### buf.length
|
### buf.length
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.90
|
added: v0.1.90
|
||||||
|
@ -686,7 +686,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
|
|||||||
// If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer.
|
// If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer.
|
||||||
// `x !== x`-style conditionals are a faster form of `isNaN(x)`
|
// `x !== x`-style conditionals are a faster form of `isNaN(x)`
|
||||||
if (byteOffset !== byteOffset) {
|
if (byteOffset !== byteOffset) {
|
||||||
byteOffset = dir ? 0 : (buffer.length - 1);
|
byteOffset = dir ? 0 : buffer.length;
|
||||||
}
|
}
|
||||||
dir = !!dir; // Cast to bool.
|
dir = !!dir; // Cast to bool.
|
||||||
|
|
||||||
|
@ -919,17 +919,16 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
|
|||||||
// Computes the offset for starting an indexOf or lastIndexOf search.
|
// Computes the offset for starting an indexOf or lastIndexOf search.
|
||||||
// Returns either a valid offset in [0...<length - 1>], ie inside the Buffer,
|
// Returns either a valid offset in [0...<length - 1>], ie inside the Buffer,
|
||||||
// or -1 to signal that there is no possible match.
|
// or -1 to signal that there is no possible match.
|
||||||
int64_t IndexOfOffset(size_t length, int64_t offset_i64, bool is_forward) {
|
int64_t IndexOfOffset(size_t length,
|
||||||
|
int64_t offset_i64,
|
||||||
|
int64_t needle_length,
|
||||||
|
bool is_forward) {
|
||||||
int64_t length_i64 = static_cast<int64_t>(length);
|
int64_t length_i64 = static_cast<int64_t>(length);
|
||||||
if (length_i64 == 0) {
|
|
||||||
// Empty buffer, no match.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (offset_i64 < 0) {
|
if (offset_i64 < 0) {
|
||||||
if (offset_i64 + length_i64 >= 0) {
|
if (offset_i64 + length_i64 >= 0) {
|
||||||
// Negative offsets count backwards from the end of the buffer.
|
// Negative offsets count backwards from the end of the buffer.
|
||||||
return length_i64 + offset_i64;
|
return length_i64 + offset_i64;
|
||||||
} else if (is_forward) {
|
} else if (is_forward || needle_length == 0) {
|
||||||
// indexOf from before the start of the buffer: search the whole buffer.
|
// indexOf from before the start of the buffer: search the whole buffer.
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@ -937,9 +936,12 @@ int64_t IndexOfOffset(size_t length, int64_t offset_i64, bool is_forward) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (offset_i64 < length_i64) {
|
if (offset_i64 + needle_length <= length_i64) {
|
||||||
// Valid positive offset.
|
// Valid positive offset.
|
||||||
return offset_i64;
|
return offset_i64;
|
||||||
|
} else if (needle_length == 0) {
|
||||||
|
// Out of buffer bounds, but empty needle: point to end of buffer.
|
||||||
|
return length_i64;
|
||||||
} else if (is_forward) {
|
} else if (is_forward) {
|
||||||
// indexOf from past the end of the buffer: no match.
|
// indexOf from past the end of the buffer: no match.
|
||||||
return -1;
|
return -1;
|
||||||
@ -974,11 +976,21 @@ void IndexOfString(const FunctionCallbackInfo<Value>& args) {
|
|||||||
const size_t needle_length =
|
const size_t needle_length =
|
||||||
StringBytes::Size(args.GetIsolate(), needle, enc);
|
StringBytes::Size(args.GetIsolate(), needle, enc);
|
||||||
|
|
||||||
if (needle_length == 0 || haystack_length == 0) {
|
int64_t opt_offset = IndexOfOffset(haystack_length,
|
||||||
|
offset_i64,
|
||||||
|
needle_length,
|
||||||
|
is_forward);
|
||||||
|
|
||||||
|
if (needle_length == 0) {
|
||||||
|
// Match String#indexOf() and String#lastIndexOf() behaviour.
|
||||||
|
args.GetReturnValue().Set(static_cast<double>(opt_offset));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (haystack_length == 0) {
|
||||||
return args.GetReturnValue().Set(-1);
|
return args.GetReturnValue().Set(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t opt_offset = IndexOfOffset(haystack_length, offset_i64, is_forward);
|
|
||||||
if (opt_offset <= -1) {
|
if (opt_offset <= -1) {
|
||||||
return args.GetReturnValue().Set(-1);
|
return args.GetReturnValue().Set(-1);
|
||||||
}
|
}
|
||||||
@ -1077,11 +1089,21 @@ void IndexOfBuffer(const FunctionCallbackInfo<Value>& args) {
|
|||||||
const char* needle = buf_data;
|
const char* needle = buf_data;
|
||||||
const size_t needle_length = buf_length;
|
const size_t needle_length = buf_length;
|
||||||
|
|
||||||
if (needle_length == 0 || haystack_length == 0) {
|
int64_t opt_offset = IndexOfOffset(haystack_length,
|
||||||
|
offset_i64,
|
||||||
|
needle_length,
|
||||||
|
is_forward);
|
||||||
|
|
||||||
|
if (needle_length == 0) {
|
||||||
|
// Match String#indexOf() and String#lastIndexOf() behaviour.
|
||||||
|
args.GetReturnValue().Set(static_cast<double>(opt_offset));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (haystack_length == 0) {
|
||||||
return args.GetReturnValue().Set(-1);
|
return args.GetReturnValue().Set(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t opt_offset = IndexOfOffset(haystack_length, offset_i64, is_forward);
|
|
||||||
if (opt_offset <= -1) {
|
if (opt_offset <= -1) {
|
||||||
return args.GetReturnValue().Set(-1);
|
return args.GetReturnValue().Set(-1);
|
||||||
}
|
}
|
||||||
@ -1132,8 +1154,8 @@ void IndexOfNumber(const FunctionCallbackInfo<Value>& args) {
|
|||||||
int64_t offset_i64 = args[2]->IntegerValue();
|
int64_t offset_i64 = args[2]->IntegerValue();
|
||||||
bool is_forward = args[3]->IsTrue();
|
bool is_forward = args[3]->IsTrue();
|
||||||
|
|
||||||
int64_t opt_offset = IndexOfOffset(ts_obj_length, offset_i64, is_forward);
|
int64_t opt_offset = IndexOfOffset(ts_obj_length, offset_i64, 1, is_forward);
|
||||||
if (opt_offset <= -1) {
|
if (opt_offset <= -1 || ts_obj_length == 0) {
|
||||||
return args.GetReturnValue().Set(-1);
|
return args.GetReturnValue().Set(-1);
|
||||||
}
|
}
|
||||||
size_t offset = static_cast<size_t>(opt_offset);
|
size_t offset = static_cast<size_t>(opt_offset);
|
||||||
|
@ -29,10 +29,10 @@ assert(b.includes('bc', -Infinity));
|
|||||||
assert(!b.includes('bc', Infinity));
|
assert(!b.includes('bc', Infinity));
|
||||||
assert(b.includes('f'), b.length - 1);
|
assert(b.includes('f'), b.length - 1);
|
||||||
assert(!b.includes('z'));
|
assert(!b.includes('z'));
|
||||||
assert(!b.includes(''));
|
assert(b.includes(''));
|
||||||
assert(!b.includes('', 1));
|
assert(b.includes('', 1));
|
||||||
assert(!b.includes('', b.length + 1));
|
assert(b.includes('', b.length + 1));
|
||||||
assert(!b.includes('', Infinity));
|
assert(b.includes('', Infinity));
|
||||||
assert(b.includes(buf_a));
|
assert(b.includes(buf_a));
|
||||||
assert(!b.includes(buf_a, 1));
|
assert(!b.includes(buf_a, 1));
|
||||||
assert(!b.includes(buf_a, -1));
|
assert(!b.includes(buf_a, -1));
|
||||||
@ -51,10 +51,10 @@ assert(b.includes(buf_bc, -Infinity));
|
|||||||
assert(!b.includes(buf_bc, Infinity));
|
assert(!b.includes(buf_bc, Infinity));
|
||||||
assert(b.includes(buf_f), b.length - 1);
|
assert(b.includes(buf_f), b.length - 1);
|
||||||
assert(!b.includes(buf_z));
|
assert(!b.includes(buf_z));
|
||||||
assert(!b.includes(buf_empty));
|
assert(b.includes(buf_empty));
|
||||||
assert(!b.includes(buf_empty, 1));
|
assert(b.includes(buf_empty, 1));
|
||||||
assert(!b.includes(buf_empty, b.length + 1));
|
assert(b.includes(buf_empty, b.length + 1));
|
||||||
assert(!b.includes(buf_empty, Infinity));
|
assert(b.includes(buf_empty, Infinity));
|
||||||
assert(b.includes(0x61));
|
assert(b.includes(0x61));
|
||||||
assert(!b.includes(0x61, 1));
|
assert(!b.includes(0x61, 1));
|
||||||
assert(!b.includes(0x61, -1));
|
assert(!b.includes(0x61, -1));
|
||||||
|
@ -31,10 +31,10 @@ assert.strictEqual(b.indexOf('bc', -Infinity), 1);
|
|||||||
assert.strictEqual(b.indexOf('bc', Infinity), -1);
|
assert.strictEqual(b.indexOf('bc', Infinity), -1);
|
||||||
assert.strictEqual(b.indexOf('f'), b.length - 1);
|
assert.strictEqual(b.indexOf('f'), b.length - 1);
|
||||||
assert.strictEqual(b.indexOf('z'), -1);
|
assert.strictEqual(b.indexOf('z'), -1);
|
||||||
assert.strictEqual(b.indexOf(''), -1);
|
assert.strictEqual(b.indexOf(''), 0);
|
||||||
assert.strictEqual(b.indexOf('', 1), -1);
|
assert.strictEqual(b.indexOf('', 1), 1);
|
||||||
assert.strictEqual(b.indexOf('', b.length + 1), -1);
|
assert.strictEqual(b.indexOf('', b.length + 1), b.length);
|
||||||
assert.strictEqual(b.indexOf('', Infinity), -1);
|
assert.strictEqual(b.indexOf('', Infinity), b.length);
|
||||||
assert.strictEqual(b.indexOf(buf_a), 0);
|
assert.strictEqual(b.indexOf(buf_a), 0);
|
||||||
assert.strictEqual(b.indexOf(buf_a, 1), -1);
|
assert.strictEqual(b.indexOf(buf_a, 1), -1);
|
||||||
assert.strictEqual(b.indexOf(buf_a, -1), -1);
|
assert.strictEqual(b.indexOf(buf_a, -1), -1);
|
||||||
@ -53,10 +53,10 @@ assert.strictEqual(b.indexOf(buf_bc, -Infinity), 1);
|
|||||||
assert.strictEqual(b.indexOf(buf_bc, Infinity), -1);
|
assert.strictEqual(b.indexOf(buf_bc, Infinity), -1);
|
||||||
assert.strictEqual(b.indexOf(buf_f), b.length - 1);
|
assert.strictEqual(b.indexOf(buf_f), b.length - 1);
|
||||||
assert.strictEqual(b.indexOf(buf_z), -1);
|
assert.strictEqual(b.indexOf(buf_z), -1);
|
||||||
assert.strictEqual(b.indexOf(buf_empty), -1);
|
assert.strictEqual(b.indexOf(buf_empty), 0);
|
||||||
assert.strictEqual(b.indexOf(buf_empty, 1), -1);
|
assert.strictEqual(b.indexOf(buf_empty, 1), 1);
|
||||||
assert.strictEqual(b.indexOf(buf_empty, b.length + 1), -1);
|
assert.strictEqual(b.indexOf(buf_empty, b.length + 1), b.length);
|
||||||
assert.strictEqual(b.indexOf(buf_empty, Infinity), -1);
|
assert.strictEqual(b.indexOf(buf_empty, Infinity), b.length);
|
||||||
assert.strictEqual(b.indexOf(0x61), 0);
|
assert.strictEqual(b.indexOf(0x61), 0);
|
||||||
assert.strictEqual(b.indexOf(0x61, 1), -1);
|
assert.strictEqual(b.indexOf(0x61, 1), -1);
|
||||||
assert.strictEqual(b.indexOf(0x61, -1), -1);
|
assert.strictEqual(b.indexOf(0x61, -1), -1);
|
||||||
@ -429,10 +429,10 @@ assert.strictEqual(b.lastIndexOf(buf_bc, -Infinity), -1);
|
|||||||
assert.strictEqual(b.lastIndexOf(buf_bc, Infinity), 1);
|
assert.strictEqual(b.lastIndexOf(buf_bc, Infinity), 1);
|
||||||
assert.strictEqual(b.lastIndexOf(buf_f), b.length - 1);
|
assert.strictEqual(b.lastIndexOf(buf_f), b.length - 1);
|
||||||
assert.strictEqual(b.lastIndexOf(buf_z), -1);
|
assert.strictEqual(b.lastIndexOf(buf_z), -1);
|
||||||
assert.strictEqual(b.lastIndexOf(buf_empty), -1);
|
assert.strictEqual(b.lastIndexOf(buf_empty), b.length);
|
||||||
assert.strictEqual(b.lastIndexOf(buf_empty, 1), -1);
|
assert.strictEqual(b.lastIndexOf(buf_empty, 1), 1);
|
||||||
assert.strictEqual(b.lastIndexOf(buf_empty, b.length + 1), -1);
|
assert.strictEqual(b.lastIndexOf(buf_empty, b.length + 1), b.length);
|
||||||
assert.strictEqual(b.lastIndexOf(buf_empty, Infinity), -1);
|
assert.strictEqual(b.lastIndexOf(buf_empty, Infinity), b.length);
|
||||||
// lastIndexOf number:
|
// lastIndexOf number:
|
||||||
assert.strictEqual(b.lastIndexOf(0x61), 0);
|
assert.strictEqual(b.lastIndexOf(0x61), 0);
|
||||||
assert.strictEqual(b.lastIndexOf(0x61, 1), 0);
|
assert.strictEqual(b.lastIndexOf(0x61, 1), 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user