mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
src: fix out-of-bounds write when transcoding odd-length ucs2
Signed-off-by: Nashit-h <nashit@bugqore.com> PR-URL: https://github.com/nodejs/node/pull/64512 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
This commit is contained in:
1 parent
467c0431d7
commit
70c189bd9d
2 files changed
+20
-2
No files matched your search
+5
-2
@@ -121,10 +121,13 @@ MaybeLocal<Object> ToBufferEndian(Environment* env, MaybeStackBuffer<T>* buf) {
|
||||
|
||||
void CopySourceBuffer(MaybeStackBuffer<UChar>* dest,
|
||||
const char* data,
|
||||
const size_t length,
|
||||
const size_t length_in_chars) {
|
||||
dest->AllocateSufficientStorage(length_in_chars);
|
||||
char* dst = reinterpret_cast<char*>(**dest);
|
||||
// The destination holds length_in_chars UChar units. Copy that many whole
|
||||
// units and ignore a trailing odd byte; copying the raw byte length would
|
||||
// write one byte past the buffer when the source length is not even.
|
||||
const size_t length = length_in_chars * sizeof(UChar);
|
||||
memcpy(dst, data, length);
|
||||
if constexpr (IsBigEndian()) {
|
||||
CHECK(nbytes::SwapBytes16(dst, length));
|
||||
@@ -197,7 +200,7 @@ MaybeLocal<Object> TranscodeFromUcs2(Environment* env,
|
||||
to.set_subst_chars(sub.c_str());
|
||||
|
||||
const size_t length_in_chars = source_length / sizeof(UChar);
|
||||
CopySourceBuffer(&sourcebuf, source, source_length, length_in_chars);
|
||||
CopySourceBuffer(&sourcebuf, source, length_in_chars);
|
||||
MaybeStackBuffer<char> destbuf(length_in_chars);
|
||||
const uint32_t len = ucnv_fromUChars(to.conv(), *destbuf, length_in_chars,
|
||||
*sourcebuf, length_in_chars, status);
|
||||
|
||||
@@ -88,3 +88,18 @@ assert.deepStrictEqual(
|
||||
{
|
||||
buffer.transcode(new buffer.Buffer.allocUnsafeSlow(1), 'utf16le', 'ucs2');
|
||||
}
|
||||
|
||||
// An odd-length ucs2 source must only convert whole 2-byte code units and
|
||||
// leave the trailing byte untouched, without reading or writing past the
|
||||
// conversion buffer. Lengths are chosen to exercise both the on-stack and the
|
||||
// heap-allocated code paths.
|
||||
for (const len of [2049, 4099]) {
|
||||
const src = Buffer.alloc(len, 0x61);
|
||||
const wholeUnits = src.subarray(0, len - 1);
|
||||
for (const to of ['latin1', 'ascii']) {
|
||||
assert.deepStrictEqual(
|
||||
buffer.transcode(src, 'utf16le', to),
|
||||
buffer.transcode(wholeUnits, 'utf16le', to),
|
||||
`ucs2->${to} odd length ${len}`);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user