From 62ba13a146dff72aa98670a1f14e87947c6591ce Mon Sep 17 00:00:00 2001 From: anvesha s Date: Mon, 2 Nov 2026 22:04:52 +0530 Subject: [PATCH] Write from the current buffer in SnappyFramedInputStream.transferTo --- .../snappy/SnappyFramedInputStream.java | 9 ++--- .../xerial/snappy/SnappyFramedStreamTest.java | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/xerial/snappy/SnappyFramedInputStream.java b/src/main/java/org/xerial/snappy/SnappyFramedInputStream.java index a513cd37..bf70c201 100644 --- a/src/main/java/org/xerial/snappy/SnappyFramedInputStream.java +++ b/src/main/java/org/xerial/snappy/SnappyFramedInputStream.java @@ -424,14 +424,13 @@ public long transferTo(WritableByteChannel wbc) throw new ClosedChannelException(); } - final ByteBuffer bb = ByteBuffer.wrap(buffer); - long totTransfered = 0; while (ensureBuffer()) { - bb.clear(); - bb.position(position); - bb.limit(position + available()); + // ensureBuffer() replaces buffer with a larger one for frames that do not fit the current buffers, + // so wrap it per frame rather than once up front, otherwise the old array, already released to the + // pool, would be written out + final ByteBuffer bb = ByteBuffer.wrap(buffer, position, available()); wbc.write(bb); diff --git a/src/test/java/org/xerial/snappy/SnappyFramedStreamTest.java b/src/test/java/org/xerial/snappy/SnappyFramedStreamTest.java index e428bf98..751187b4 100644 --- a/src/test/java/org/xerial/snappy/SnappyFramedStreamTest.java +++ b/src/test/java/org/xerial/snappy/SnappyFramedStreamTest.java @@ -265,6 +265,44 @@ public void testTransferTo_WritableByteChannel() assertArrayEquals(random, baos.toByteArray()); } + @Test + public void testTransferTo_WritableByteChannel_largerFrame() + throws IOException + { + // A frame larger than the initial buffers makes the stream replace its byte[] buffer while + // transferTo is running, so the data must still come from the current buffer + final byte[] random = getRandom(0.5, 100000); + + final byte[] stream = new byte[HEADER_BYTES.length + 8 + random.length]; + System.arraycopy(HEADER_BYTES, 0, stream, 0, HEADER_BYTES.length); + + stream[10] = UNCOMPRESSED_DATA_FLAG; + + int length = random.length + 4; + stream[11] = (byte) length; + stream[12] = (byte) (length >>> 8); + stream[13] = (byte) (length >>> 16); + + int crc32c = maskedCrc32c(random); + stream[14] = (byte) crc32c; + stream[15] = (byte) (crc32c >>> 8); + stream[16] = (byte) (crc32c >>> 16); + stream[17] = (byte) (crc32c >>> 24); + + System.arraycopy(random, 0, stream, 18, random.length); + + final SnappyFramedInputStream sfis = new SnappyFramedInputStream( + new ByteArrayInputStream(stream)); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream( + random.length); + final WritableByteChannel wbc = Channels.newChannel(baos); + sfis.transferTo(wbc); + wbc.close(); + + assertArrayEquals(random, baos.toByteArray()); + } + @Test public void testLargerFrames_raw_() throws IOException