From 107248f88e0599390af058b274a546bdfa6b1efd Mon Sep 17 00:00:00 2001 From: Arnav Balyan Date: Thu, 23 Jul 2026 19:26:31 +0530 Subject: [PATCH] update --- .../blob/AbstractBlobElementReader.java | 6 ++ .../blob/BlobInlineReadOverflowTest.java | 67 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 paimon-format/src/test/java/org/apache/paimon/format/blob/BlobInlineReadOverflowTest.java diff --git a/paimon-format/src/main/java/org/apache/paimon/format/blob/AbstractBlobElementReader.java b/paimon-format/src/main/java/org/apache/paimon/format/blob/AbstractBlobElementReader.java index ed9e695dfdd4..51af6d0dc421 100644 --- a/paimon-format/src/main/java/org/apache/paimon/format/blob/AbstractBlobElementReader.java +++ b/paimon-format/src/main/java/org/apache/paimon/format/blob/AbstractBlobElementReader.java @@ -64,6 +64,12 @@ protected final Blob readBlob(long position, long length) { } protected final byte[] readInlineBlob(long position, long length) { + Preconditions.checkArgument( + length <= Integer.MAX_VALUE, + "Inline BLOB is too large to read into memory: %s bytes (max %s). " + + "Use 'blob-as-descriptor' = true to read it as a descriptor.", + length, + Integer.MAX_VALUE); byte[] blobData = new byte[(int) length]; SeekableInputStream in = inputStream(); try { diff --git a/paimon-format/src/test/java/org/apache/paimon/format/blob/BlobInlineReadOverflowTest.java b/paimon-format/src/test/java/org/apache/paimon/format/blob/BlobInlineReadOverflowTest.java new file mode 100644 index 000000000000..930a86b19b18 --- /dev/null +++ b/paimon-format/src/test/java/org/apache/paimon/format/blob/BlobInlineReadOverflowTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.paimon.format.blob; + +import org.apache.paimon.data.Blob; +import org.apache.paimon.fs.ByteArraySeekableStream; +import org.apache.paimon.fs.Path; +import org.apache.paimon.fs.local.LocalFileIO; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** Tests reading a BLOB whose inline payload exceeds {@link Integer#MAX_VALUE} bytes. */ +class BlobInlineReadOverflowTest { + + private static BlobElementSerializer.Reader inlineReader(byte[] onDisk) { + return new RawBlobElementSerializer() + .createReader( + LocalFileIO.create(), + new Path("/tmp/does-not-exist.blob"), + new ByteArraySeekableStream(onDisk), + false); + } + + @Test + void testOversizedInlineBlobThrowsInsteadOfTruncating() { + long declaredLength = (1L << 32) + 16; + + BlobElementSerializer.Reader reader = inlineReader(new byte[16]); + + assertThatThrownBy(() -> reader.read(0, declaredLength)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Inline BLOB is too large") + .hasMessageContaining("blob-as-descriptor"); + } + + @Test + void testInlineBlobWithinLimitReadsFully() { + byte[] onDisk = new byte[16]; + for (int i = 0; i < onDisk.length; i++) { + onDisk[i] = (byte) i; + } + + BlobElementSerializer.Reader reader = inlineReader(onDisk); + + Blob blob = (Blob) reader.read(0, onDisk.length); + assertThat(blob.toData()).isEqualTo(onDisk); + } +}