You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2022/02/18 08:18:29 UTC

[arrow] branch master updated: ARROW-15502: [Java] Detect exceptional footer size in Arrow file reader

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

liyafan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new f49547b  ARROW-15502: [Java] Detect exceptional footer size in Arrow file reader
f49547b is described below

commit f49547b1504d9a514fd847307a2a6715959dc5e1
Author: liyafan82 <fa...@foxmail.com>
AuthorDate: Fri Feb 18 16:16:28 2022 +0800

    ARROW-15502: [Java] Detect exceptional footer size in Arrow file reader
    
    When a malformed Arrow file containing an extremely large footer size (much larger than the file size) is fed to the ArrowFileReader, our implementation fails detect the problem, due to integer arithmetic overflow.
    
    This will lead to extremely large memory allocation and eventually causing an OutOfMemoryError.
    
    Closes #12296 from liyafan82/fly_0130_rd
    
    Authored-by: liyafan82 <fa...@foxmail.com>
    Signed-off-by: liyafan82 <fa...@foxmail.com>
---
 .../apache/arrow/vector/ipc/ArrowFileReader.java   |  3 +-
 .../arrow/vector/ipc/TestArrowReaderWriter.java    | 33 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java b/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java
index f4e9e0d..8629cf9 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java
@@ -98,7 +98,8 @@ public class ArrowFileReader extends ArrowReader {
         throw new InvalidArrowFileException("missing Magic number " + Arrays.toString(buffer.array()));
       }
       int footerLength = MessageSerializer.bytesToInt(array);
-      if (footerLength <= 0 || footerLength + ArrowMagic.MAGIC_LENGTH * 2 + 4 > in.size()) {
+      if (footerLength <= 0 || footerLength + ArrowMagic.MAGIC_LENGTH * 2 + 4 > in.size() ||
+              footerLength > footerLengthOffset) {
         throw new InvalidArrowFileException("invalid footer length: " + footerLength);
       }
       long footerOffset = footerLengthOffset - footerLength;
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/ipc/TestArrowReaderWriter.java b/java/vector/src/test/java/org/apache/arrow/vector/ipc/TestArrowReaderWriter.java
index 1167819..55cab72 100644
--- a/java/vector/src/test/java/org/apache/arrow/vector/ipc/TestArrowReaderWriter.java
+++ b/java/vector/src/test/java/org/apache/arrow/vector/ipc/TestArrowReaderWriter.java
@@ -89,6 +89,7 @@ import org.apache.arrow.vector.util.DictionaryUtility;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
 
 public class TestArrowReaderWriter {
 
@@ -879,4 +880,36 @@ public class TestArrowReaderWriter {
       }
     }
   }
+
+  /**
+   * This test case covers the case for which the footer size is extremely large
+   * (much larger than the file size).
+   * Due to integer overflow, our implementation fails detect the problem, which
+   * leads to extremely large memory allocation and eventually causing an OutOfMemoryError.
+   */
+  @Test
+  public void testFileFooterSizeOverflow() {
+    // copy of org.apache.arrow.vector.ipc.ArrowMagic#MAGIC
+    final byte[] magicBytes = "ARROW1".getBytes(StandardCharsets.UTF_8);
+
+    // prepare input data
+    byte[] data = new byte[30];
+    System.arraycopy(magicBytes, 0, data, 0, ArrowMagic.MAGIC_LENGTH);
+    int footerLength = Integer.MAX_VALUE;
+    byte[] footerLengthBytes =
+            ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(footerLength).array();
+    int footerOffset = data.length - ArrowMagic.MAGIC_LENGTH - 4;
+    System.arraycopy(footerLengthBytes, 0, data, footerOffset, 4);
+    System.arraycopy(magicBytes, 0, data, footerOffset + 4, ArrowMagic.MAGIC_LENGTH);
+
+    // test file reader
+    InvalidArrowFileException e = Assertions.assertThrows(InvalidArrowFileException.class, () -> {
+      try (SeekableReadChannel channel = new SeekableReadChannel(new ByteArrayReadableSeekableByteChannel(data));
+           ArrowFileReader reader = new ArrowFileReader(channel, allocator)) {
+        reader.getVectorSchemaRoot().getSchema();
+      }
+    });
+
+    assertEquals("invalid footer length: " + footerLength, e.getMessage());
+  }
 }