Skip to content

Commit 4fad276

Browse files
committed
GH-1196: Write NO_COMPRESSION_LENGTH sentinel for empty buffers in compress()
1 parent 21b6a05 commit 4fad276

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

compression/src/test/java/org/apache/arrow/compression/TestCompressionCodec.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,35 @@ void testEmptyBuffer(int vectorLength, CompressionCodec codec) throws Exception
233233
AutoCloseables.close(decompressedBuffers);
234234
}
235235

236+
static Stream<CompressionCodec> compressingCodecs() {
237+
return Stream.of(new Lz4CompressionCodec(), new ZstdCompressionCodec());
238+
}
239+
240+
@ParameterizedTest
241+
@MethodSource("compressingCodecs")
242+
void testEmptyBufferWritesUncompressedSentinel(CompressionCodec codec) {
243+
// GH-1196: an empty buffer must be encoded with the uncompressed-length
244+
// sentinel (-1), not 0. A 0 prefix is undefined in the Arrow IPC format and
245+
// is rejected by the C++ and Python implementations, even though Java itself
246+
// accepts it on read.
247+
ArrowBuf empty = allocator.buffer(1);
248+
empty.writerIndex(0);
249+
250+
// compress() takes ownership of and closes the input buffer
251+
ArrowBuf compressed = codec.compress(allocator, empty);
252+
253+
assertEquals(
254+
CompressionUtil.NO_COMPRESSION_LENGTH,
255+
compressed.getLong(0),
256+
"empty buffer must use the -1 uncompressed sentinel, not 0");
257+
258+
// and it must still round-trip back to an empty buffer
259+
ArrowBuf decompressed = codec.decompress(allocator, compressed);
260+
assertEquals(0L, decompressed.writerIndex());
261+
262+
decompressed.close();
263+
}
264+
236265
@Test
237266
void testLz4DecompressRejectsWrongLength() {
238267
byte[] data = new byte[512]; // all zeros, highly compressible

vector/src/main/java/org/apache/arrow/vector/compression/AbstractCompressionCodec.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public ArrowBuf compress(BufferAllocator allocator, ArrowBuf uncompressedBuffer)
3636
if (uncompressedLength == 0L) {
3737
// shortcut for empty buffer
3838
ArrowBuf compressedBuffer = allocator.buffer(CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH);
39-
compressedBuffer.setLong(0, 0);
39+
compressedBuffer.setLong(0, CompressionUtil.NO_COMPRESSION_LENGTH);
4040
compressedBuffer.writerIndex(CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH);
4141
uncompressedBuffer.close();
4242
return compressedBuffer;

0 commit comments

Comments
 (0)