From e939bf15ba582952adc1491229567587d7f74318 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Thu, 8 Oct 2026 14:17:33 +0000 Subject: [PATCH] buffer: fix unaligned UTF-16LE decoding For odd-length input, the destination only has room for complete code units. Copy those units and ignore the trailing byte. This matches the aligned and big-endian paths. Backport of https://github.com/nodejs/node/pull/65905 (commit b805fb5158a) to the v24.x release line. Assisted-by: pi Signed-off-by: Matteo Collina --- src/string_bytes.cc | 4 ++-- test/parallel/test-buffer-tostring.js | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/string_bytes.cc b/src/string_bytes.cc index b39d6fcc2ecb..656b82458007 100644 --- a/src/string_bytes.cc +++ b/src/string_bytes.cc @@ -722,8 +722,8 @@ MaybeLocal StringBytes::Encode(Isolate* isolate, } if (reinterpret_cast(buf) % 2 != 0) { return EncodeTwoByteString( - isolate, str_len, [buf, buflen](uint16_t* dst) { - memcpy(dst, buf, buflen); + isolate, str_len, [buf, str_len](uint16_t* dst) { + memcpy(dst, buf, str_len * sizeof(*dst)); }); } return ExternTwoByteString::NewFromCopy( diff --git a/test/parallel/test-buffer-tostring.js b/test/parallel/test-buffer-tostring.js index a3dad0146d75..676d2f85f567 100644 --- a/test/parallel/test-buffer-tostring.js +++ b/test/parallel/test-buffer-tostring.js @@ -9,6 +9,13 @@ for (const encoding of ['utf8', 'utf-8', 'ucs2', 'ucs-2', 'ascii', 'latin1', assert.strictEqual(Buffer.from('foo', encoding).toString(encoding), 'foo'); } +// Ignore an incomplete trailing code unit when decoding unaligned UTF-16LE. +for (const size of [514, 516]) { + const buffer = Buffer.alloc(size, 0x61); + assert.strictEqual(buffer.toString('utf16le', 1), + '\u6161'.repeat((size - 1) >>> 1)); +} + // base64 ['base64', 'BASE64'].forEach((encoding) => { assert.strictEqual(Buffer.from('Zm9v', encoding).toString(encoding), 'Zm9v');