Skip to content
Open
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
28 changes: 17 additions & 11 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -983,8 +983,8 @@ void IndexOfString(const FunctionCallbackInfo<Value>& args) {
if (!StringBytes::Size(isolate, needle, enc).To(&needle_length)) return;

// search_end is the exclusive upper bound of the search range.
size_t search_end = static_cast<size_t>(
std::min(end_i64, static_cast<int64_t>(haystack_length)));
size_t search_end = static_cast<size_t>(std::min(
std::max(end_i64, int64_t{0}), static_cast<int64_t>(haystack_length)));
if (enc == UCS2) search_end &= ~static_cast<size_t>(1);

int64_t opt_offset = IndexOfOffset(haystack_length,
Expand All @@ -993,8 +993,11 @@ void IndexOfString(const FunctionCallbackInfo<Value>& args) {
is_forward);

if (needle_length == 0) {
// Match String#indexOf() and String#lastIndexOf() behavior.
args.GetReturnValue().Set(static_cast<double>(opt_offset));
// Match String#indexOf() and String#lastIndexOf() behavior,
// but clamp to search_end.
int64_t clamped =
std::min(opt_offset, static_cast<int64_t>(search_end));
args.GetReturnValue().Set(static_cast<double>(clamped));
return;
}

Expand Down Expand Up @@ -1108,8 +1111,8 @@ void IndexOfBuffer(const FunctionCallbackInfo<Value>& args) {
const size_t needle_length = needle_contents.length();

// search_end is the exclusive upper bound of the search range.
size_t search_end = static_cast<size_t>(
std::min(end_i64, static_cast<int64_t>(haystack_length)));
size_t search_end = static_cast<size_t>(std::min(
std::max(end_i64, int64_t{0}), static_cast<int64_t>(haystack_length)));
if (enc == UCS2) search_end &= ~static_cast<size_t>(1);

int64_t opt_offset = IndexOfOffset(haystack_length,
Expand All @@ -1118,8 +1121,11 @@ void IndexOfBuffer(const FunctionCallbackInfo<Value>& args) {
is_forward);

if (needle_length == 0) {
// Match String#indexOf() and String#lastIndexOf() behavior.
args.GetReturnValue().Set(static_cast<double>(opt_offset));
// Match String#indexOf() and String#lastIndexOf() behavior,
// but clamp to search_end.
int64_t clamped =
std::min(opt_offset, static_cast<int64_t>(search_end));
args.GetReturnValue().Set(static_cast<double>(clamped));
return;
}

Expand Down Expand Up @@ -1184,8 +1190,8 @@ int32_t IndexOfNumberImpl(Local<Value> buffer_obj,
}
size_t offset = static_cast<size_t>(opt_offset);
// search_end is the exclusive upper bound of the search range.
size_t search_end = static_cast<size_t>(
std::min(end_i64, static_cast<int64_t>(buffer_length)));
size_t search_end = static_cast<size_t>(std::min(
std::max(end_i64, int64_t{0}), static_cast<int64_t>(buffer_length)));

const void* ptr;
if (is_forward) {
Expand Down Expand Up @@ -1222,8 +1228,8 @@ int32_t FastIndexOfNumber(Local<Value>,
Local<Value> buffer_obj,
uint32_t needle,
int64_t offset_i64,
int64_t end_i64,
bool is_forward,
int64_t end_i64,
// NOLINTNEXTLINE(runtime/references)
FastApiCallbackOptions& options) {
HandleScope scope(options.isolate);
Expand Down
35 changes: 35 additions & 0 deletions test/parallel/test-buffer-indexof.js
Original file line number Diff line number Diff line change
Expand Up @@ -691,3 +691,38 @@

assert.strictEqual(buf.includes('c'), true);
}

{
const buf = Buffer.from('abcabc');

// negative end should be treated as 0 (no match possible).

Check failure on line 698 in test/parallel/test-buffer-indexof.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Comments should not begin with a lowercase character
assert.strictEqual(buf.indexOf('a', 0, -1), -1);
assert.strictEqual(buf.indexOf('a', 0, -100), -1);
assert.strictEqual(buf.indexOf(0x61, 0, -1), -1);
assert.strictEqual(buf.lastIndexOf('a', 5, -1), -1);
assert.strictEqual(buf.lastIndexOf(0x61, 5, -1), -1);
assert.strictEqual(buf.includes('a', 0, -1), false);
assert.strictEqual(buf.indexOf(Buffer.from('a'), 0, -1), -1);
assert.strictEqual(buf.lastIndexOf(Buffer.from('a'), 5, -1), -1);

// end = 0 means empty search range.
assert.strictEqual(buf.indexOf('a', 0, 0), -1);
assert.strictEqual(buf.indexOf(0x61, 0, 0), -1);
assert.strictEqual(buf.lastIndexOf('a', 5, 0), -1);
assert.strictEqual(buf.lastIndexOf(0x61, 5, 0), -1);

// end greater than buffer length should be clamped.

Check failure on line 714 in test/parallel/test-buffer-indexof.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Comments should not begin with a lowercase character
assert.strictEqual(buf.indexOf('c', 0, 100), 2);
assert.strictEqual(buf.indexOf(0x63, 0, 100), 2);
assert.strictEqual(buf.lastIndexOf('c', 5, 100), 5);
assert.strictEqual(buf.lastIndexOf(0x63, 5, 100), 5);
assert.strictEqual(buf.indexOf(Buffer.from('c'), 0, 100), 2);

// empty needle with end parameter should clamp to search_end.

Check failure on line 721 in test/parallel/test-buffer-indexof.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Comments should not begin with a lowercase character
assert.strictEqual(buf.indexOf('', 0, 3), 0);
assert.strictEqual(buf.indexOf('', 5, 3), 3);
assert.strictEqual(buf.indexOf(Buffer.from(''), 5, 3), 3);
assert.strictEqual(buf.indexOf('', 0, 0), 0);
assert.strictEqual(buf.lastIndexOf('', 5, 3), 3);
assert.strictEqual(buf.lastIndexOf(Buffer.from(''), 5, 3), 3);
}
Loading