Core: Reject negative ByteBuffer stream seeks - #17963
Conversation
Validate seek positions before resetting buffer state so invalid offsets fail consistently without changing the current position. Generated-by: Codex
|
Hi @laskoviymishka, would you be willing to review this ByteBufferInputStream boundary fix? It makes both implementations reject negative seeks consistently while preserving stream state, includes shared regression coverage, and all 42 CI checks pass. Thanks! |
|
|
||
| @Override | ||
| public void seek(long newPosition) throws IOException { | ||
| Preconditions.checkArgument(newPosition >= 0, "Position is negative: %s", newPosition); |
There was a problem hiding this comment.
when can this be negative ?
There was a problem hiding this comment.
newPosition is supplied by the caller through the public ByteBufferInputStream.wrap(...).seek(...) API. I have not identified a production call path that supplies a negative offset; I found this while testing invalid seek inputs.
On the base revision, after reading the first byte and then calling seek(-1), SingleBufferInputStream throws IllegalArgumentException but has already reset its position to 0, while MultiBufferInputStream accepts the call and also resets to 0. I reproduced both cases: the next read returns the first byte again. With this change, both reject the invalid offset while keeping position 1, and the next read returns the second byte.
The motivation is defensive validation before mutating stream state, consistent with the existing negative-seek guards in EagerInputStream, S3InputStream, and GCSInputStream. The shared regression test checks rejection and position preservation for both implementations.
|
+1 here, please address any additional concerns from committers |
Summary
Motivation
The two
ByteBufferInputStreamimplementations handled negative positions inconsistently.MultiBufferInputStreamsilently acceptedseek(-1)and reset to the beginning, whileSingleBufferInputStreamfailed later insideByteBuffer.positionafter it had already reset its state.Both implementations now reject the invalid position before changing state, matching the behavior of Iceberg's other seekable streams.
Testing
./gradlew :iceberg-core:spotlessApply :iceberg-core:test./gradlew :iceberg-core:spotlessCheck :iceberg-core:test --tests org.apache.iceberg.io.TestSingleBufferInputStream --tests org.apache.iceberg.io.TestMultiBufferInputStreamAI Disclosure