This is an automated email from the ASF dual-hosted git repository.

xiangfu0 pushed a commit to branch xiangfu0/codex/codec-stack/02-runtime
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to 
refs/heads/xiangfu0/codex/codec-stack/02-runtime by this push:
     new 7c5dfae64c9 Address codec runtime review nits
7c5dfae64c9 is described below

commit 7c5dfae64c9af6315a9ae5991e045a72bcb6d53a
Author: Xiang Fu <[email protected]>
AuthorDate: Mon Aug 24 18:35:26 2026 -0700

    Address codec runtime review nits
---
 .../segment/local/io/codec/CodecBufferUtils.java     |  6 +++---
 .../pinot/segment/local/io/codec/CodecContext.java   |  3 +--
 .../local/io/codec/CodecPipelineExecutor.java        |  2 +-
 .../segment/local/io/codec/ZstdCodecDefinition.java  |  6 ++++--
 .../io/codec/CompressionCodecCorruptInputTest.java   | 20 ++++++++++++++++++++
 5 files changed, 29 insertions(+), 8 deletions(-)

diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecBufferUtils.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecBufferUtils.java
index 30c5f50911d..057c574e98a 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecBufferUtils.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecBufferUtils.java
@@ -26,14 +26,14 @@ import org.apache.pinot.segment.spi.memory.CleanerUtil;
 /// Package-private buffer helpers shared across codec handler implementations.
 final class CodecBufferUtils {
 
+  private CodecBufferUtils() {
+  }
+
   /// Sanity cap (1 GiB) on any decompressed size declared by untrusted 
encoded segment data. A
   /// corrupt or hostile declaration must never drive a giant pre-allocation; 
1 GiB is well above
   /// any realistic chunk size.
   static final long MAX_DECLARED_DECOMPRESSED_SIZE = 1L << 30;
 
-  private CodecBufferUtils() {
-  }
-
   /// Validates a decompressed size declared by untrusted segment data and 
returns it when in range.
   ///
   /// Shared by every codec definition so the bound cannot be omitted from a 
new codec or silently
diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecContext.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecContext.java
index 0d813b3cc9f..011f6d958f4 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecContext.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecContext.java
@@ -18,7 +18,6 @@
  */
 package org.apache.pinot.segment.local.io.codec;
 
-import java.util.Objects;
 import org.apache.pinot.spi.data.FieldSpec.DataType;
 
 
@@ -30,7 +29,7 @@ final class CodecContext {
   private final DataType _dataType;
 
   CodecContext(DataType dataType) {
-    _dataType = Objects.requireNonNull(dataType, "dataType");
+    _dataType = dataType;
   }
 
   /// Returns the stored [DataType] of the column being indexed.
diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecPipelineExecutor.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecPipelineExecutor.java
index fb6657725df..4e4c8b56877 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecPipelineExecutor.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/CodecPipelineExecutor.java
@@ -357,7 +357,7 @@ public final class CodecPipelineExecutor {
   public void decode(ByteBuffer src, ByteBuffer dst, int expectedDecodedSize, 
int maxIntermediateSize,
       long maxCumulativeSize, DecodeScratch scratch)
       throws IOException {
-    Preconditions.checkNotNull(scratch, "scratch").ensureOpen();
+    scratch.ensureOpen();
     Preconditions.checkArgument(!_requiresDirectDstBuffer || dst.isDirect(),
         "decode(src, dst) requires a direct ByteBuffer for pipeline: %s", 
_canonicalSpec);
     Preconditions.checkArgument(expectedDecodedSize >= 0 && 
expectedDecodedSize <= dst.capacity(),
diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/ZstdCodecDefinition.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/ZstdCodecDefinition.java
index 03caa98af48..559b39475c4 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/ZstdCodecDefinition.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/io/codec/ZstdCodecDefinition.java
@@ -196,11 +196,13 @@ final class ZstdCodecDefinition implements 
ChunkCodecHandler<ZstdCodecDefinition
     dst.clear();
     ByteBuffer directSrc = CodecBufferUtils.toDirectBuffer(src);
     try {
-      long decompressedSize = Zstd.getFrameContentSize(directSrc);
+      long declaredDecompressedSize = Zstd.getFrameContentSize(directSrc);
       // As in decode(), zero is a valid known size; only Zstd's negative 
sentinel values are errors.
-      if (decompressedSize < 0) {
+      if (declaredDecompressedSize < 0) {
         throw new IOException("Zstd: cannot determine decompressed size from 
frame header");
       }
+      int decompressedSize = CodecBufferUtils.checkDeclaredDecompressedSize(
+          declaredDecompressedSize, "Zstd", "frame header");
       if (decompressedSize > dst.capacity()) {
         throw new IllegalArgumentException(
             "Zstd: decompressed size " + decompressedSize + " exceeds dst 
capacity " + dst.capacity());
diff --git 
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/codec/CompressionCodecCorruptInputTest.java
 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/codec/CompressionCodecCorruptInputTest.java
index 7b39cccc60a..99a0e2a0914 100644
--- 
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/codec/CompressionCodecCorruptInputTest.java
+++ 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/codec/CompressionCodecCorruptInputTest.java
@@ -61,6 +61,26 @@ public class CompressionCodecCorruptInputTest {
             garbage(64)));
   }
 
+  @Test
+  public void testZstdDecodeIntoRejectsOversizedDeclaredSize() {
+    // decodeInto must apply the shared sanity cap before its later 
destination-capacity check.
+    ByteBuffer dst = ByteBuffer.allocateDirect(16);
+    IOException exception = expectThrows(IOException.class,
+        () -> ZstdCodecDefinition.INSTANCE.decodeInto(
+            ZstdCodecDefinition.INSTANCE.parseOptions(List.of()), CTX, 
oversizedZstdFrame(), dst));
+    assertTrue(exception.getMessage().contains("out of range"), 
exception.getMessage());
+  }
+
+  /// Frame header whose content-size field declares (1 << 30) + 1 
decompressed bytes.
+  private static ByteBuffer oversizedZstdFrame() {
+    ByteBuffer frame = ByteBuffer.allocateDirect(9);
+    frame.put(new byte[]{
+        0x28, (byte) 0xB5, 0x2F, (byte) 0xFD, (byte) 0xA0, 0x01, 0x00, 0x00, 
0x40
+    });
+    frame.flip();
+    return frame;
+  }
+
   @Test
   public void testSnappyDecodeRejectsGarbage() {
     assertThrows(Exception.class,


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to