LuciferYang opened a new issue, #9617: URL: https://github.com/apache/paimon/issues/9617
### Search before asking - [x] I searched in the [issues](https://github.com/apache/paimon/issues) and found nothing similar. ### Paimon version master, `475be566f` (2.1-SNAPSHOT). ### Compute Engine Spark and Flink. `descriptor_to_string` and `descriptor_to_presigned_url` are registered scalar functions over `BINARY`, so the bytes come straight from the query; the same code also runs when a blob column's descriptor is read back through `Blob.fromBytes` or `FlinkRowWrapper`. ### Minimal reproduce step Take a valid video-frame descriptor and overwrite its 4-byte URI length field with a value near `Integer.MAX_VALUE`: ```java VideoFrameDescriptor descriptor = new VideoFrameDescriptor("file:/video.mp4", 0, 9, 7); byte[] bytes = descriptor.serialize(); ByteBuffer.wrap(bytes) .order(ByteOrder.LITTLE_ENDIAN) .putInt(Byte.BYTES + Long.BYTES, Integer.MAX_VALUE - 23); VideoFrameDescriptor.deserialize(bytes); ``` This throws `OutOfMemoryError: Java heap space` on a default heap, and on a large enough heap it allocates a 2GB array and then fails with `BufferUnderflowException`. Through SQL the same thing happens on an executor for `SELECT descriptor_to_string(<those bytes>)`. The length check adds before it compares: ```java int uriLength = buffer.getInt(); if (uriLength < 0 || buffer.remaining() < uriLength + 3 * Long.BYTES) { throw invalidPayload("invalid URI length: " + uriLength); } byte[] uriBytes = new byte[uriLength]; ``` With `uriLength = Integer.MAX_VALUE - 23`, `uriLength + 24` wraps to `Integer.MIN_VALUE`, so `buffer.remaining() < Integer.MIN_VALUE` is false and the check passes. `new byte[uriLength]` then tries to allocate the array. ### What doesn't meet your expectations? Malformed descriptor bytes should be rejected with the `IllegalArgumentException` that every other malformed case in this method produces, not with an `OutOfMemoryError` from a 2GB allocation. The sibling `BlobDescriptor.deserialize`, which dispatches to this one by magic number, already gets this right and validates by subtraction with one message per case: ```java if (uriLength < 0) { throw invalidPayload("negative URI length: " + uriLength); } if (uriLength > buffer.remaining()) { throw invalidPayload("URI length exceeds data size"); } if (buffer.remaining() - uriLength < Long.BYTES + Long.BYTES) { throw invalidPayload("missing offset/length"); } ``` `VideoFrameDescriptor` is the one of the two that folded all three into a single addition. ### Anything else? Nothing in the write path produces a `uriLength` like this, so reaching it needs either crafted input to one of the descriptor functions or a corrupted blob column. ### Are you willing to submit a PR? - [x] I'm willing to submit a PR! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
