From bd8f96e0ac3ca73a590a30fed25996bf4edbca00 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 13 Jun 2026 21:25:13 -0400 Subject: [PATCH] buffer: validate copyArrayBuffer offsets against buffer length CopyArrayBuffer() computed `byteLength - offset` in unsigned arithmetic before its CHECK_GE bounds check. An offset greater than the buffer length wrapped the subtraction to a near-SIZE_MAX value, so the check passed and memcpy() copied out of bounds. process.binding('buffer').copyArrayBuffer() is an internal, trusted binding; the only in-tree caller, the Web Streams BYOB reader, already validates the offsets in JS. Assert the offsets are within bounds with CHECK_LE before the subtractions so the invariant holds regardless of caller, matching the CHECK-based style already used here. Signed-off-by: Ilia Alshanetsky --- src/node_buffer.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 9adb02517efc42..81c3894a3914e2 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -1569,6 +1569,10 @@ void CopyArrayBuffer(const FunctionCallbackInfo& args) { uint32_t source_offset = args[3].As()->Value(); size_t bytes_to_copy = args[4].As()->Value(); + // Assert the offsets are within bounds before the subtractions below, which + // would otherwise underflow and defeat the bytes_to_copy bounds checks. + CHECK_LE(destination_offset, destination_byte_length); + CHECK_LE(source_offset, source_byte_length); CHECK_GE(destination_byte_length - destination_offset, bytes_to_copy); CHECK_GE(source_byte_length - source_offset, bytes_to_copy);