Skip to content

Commit 54b4e37

Browse files
authored
buffer: prevent abort on indexOf with lone surrogate needle
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com> PR-URL: #65430 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent f9f3fa9 commit 54b4e37

2 files changed

Lines changed: 30 additions & 2 deletions

File tree

src/string_bytes.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,10 @@ Maybe<size_t> StringBytes::Size(Isolate* isolate,
533533
return Just<size_t>(simdutf::utf8_length_from_latin1(
534534
reinterpret_cast<const char*>(view.data8()), view.length()));
535535
}
536-
return Just<size_t>(simdutf::utf8_length_from_utf16(
537-
reinterpret_cast<const char16_t*>(view.data16()), view.length()));
536+
return Just<size_t>(
537+
simdutf::utf8_length_from_utf16_with_replacement(
538+
reinterpret_cast<const char16_t*>(view.data16()), view.length())
539+
.count);
538540

539541
case UCS2:
540542
return Just(view.length() * sizeof(uint16_t));

test/parallel/test-buffer-indexof.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,32 @@ assert.strictEqual(reallyLong.lastIndexOf(pattern), 0);
619619
assert.strictEqual(haystack.lastIndexOf(needle), haystack.length - 3);
620620
}
621621

622+
// UTF-8 string search should use the same replacement-character semantics
623+
// as Buffer.from() for unpaired UTF-16 surrogates.
624+
{
625+
const prefix = 'a'.repeat(16);
626+
const suffix = 'b'.repeat(16);
627+
const needles = [
628+
`${prefix}${String.fromCharCode(0xd800)}${suffix}`,
629+
`${prefix}${String.fromCharCode(0xdc00)}${suffix}`,
630+
JSON.parse(`{"needle":"${prefix}\\ud800${suffix}"}`).needle,
631+
];
632+
633+
for (const needle of needles) {
634+
const needleBuffer = Buffer.from(needle, 'utf8');
635+
const haystack = Buffer.concat([
636+
Buffer.from('xx'),
637+
needleBuffer,
638+
Buffer.from('yy'),
639+
]);
640+
641+
assert.strictEqual(Buffer.byteLength(needle, 'utf8'), needleBuffer.length);
642+
assert.strictEqual(haystack.indexOf(needle, 0, 'utf8'), 2);
643+
assert.strictEqual(haystack.lastIndexOf(needle, haystack.length - 1, 'utf8'), 2);
644+
assert.strictEqual(haystack.includes(needle, 0, 'utf8'), true);
645+
}
646+
}
647+
622648
// Avoid abort because of invalid usage
623649
// see https://github.com/nodejs/node/issues/32753
624650
{

0 commit comments

Comments
 (0)