You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opennlp.apache.org by kr...@apache.org on 2026/08/14 03:17:32 UTC

(opennlp) 14/16: util: Pin tar skip and metadata expansion limits (failing tests)

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

krickert pushed a commit to branch OPENNLP-1909-resource-installer
in repository https://gitbox.apache.org/repos/asf/opennlp.git

commit 8e1fff479a2051e2d293e503eb0d5b20eac23f15
Author: Kristian Rickert <kr...@gmail.com>
AuthorDate: Wed Aug 12 15:42:08 2026 -0400

    util: Pin tar skip and metadata expansion limits (failing tests)
---
 .../opennlp/tools/util/ResourceInstallerTest.java  | 28 +++++++++++++++++++---
 .../opennlp/tools/util/archive/TarStreamTest.java  | 12 +++++-----
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/ResourceInstallerTest.java b/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/ResourceInstallerTest.java
index 8477ae697..ff0aac94c 100644
--- a/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/ResourceInstallerTest.java
+++ b/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/ResourceInstallerTest.java
@@ -43,6 +43,8 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
+import opennlp.tools.util.archive.TarArchives;
+
 import static opennlp.tools.util.InstallerTestSupport.BLOCK;
 import static opennlp.tools.util.InstallerTestSupport.KIBIBYTE;
 import static opennlp.tools.util.InstallerTestSupport.MEBIBYTE;
@@ -581,6 +583,25 @@ public class ResourceInstallerTest {
         EXPANSION_CEILING_ERROR);
   }
 
+  /**
+   * Proves that tar metadata is part of the expanded stream budget. A gzip stream made
+   * only of highly compressible pax metadata must not bypass the expansion ceiling just
+   * because it installs no regular-file content.
+   */
+  @Test
+  void testTarMetadataCountsTowardExpansionCeiling(@TempDir Path source,
+      @TempDir Path target) throws Exception {
+    final ByteArrayOutputStream tar = new ByteArrayOutputStream();
+    TarArchives.entry(tar, "pax_global_header",
+        TarArchives.paxRecord("comment", "a".repeat(64 * 1024)), 'g');
+    tar.write(new byte[TERMINATOR_SIZE]);
+    final Path file = source.resolve("metadata-bomb.tar.gz");
+    Files.write(file, gzip(tar.toByteArray()));
+
+    assertInstallFails(file, target, ceilings(MEBIBYTE, KIBIBYTE),
+        EXPANSION_CEILING_ERROR);
+  }
+
   /**
    * Proves the expansion ceiling on zip content: highly compressible entries that
    * expand beyond the ceiling are rejected and nothing is installed.
@@ -682,8 +703,8 @@ public class ResourceInstallerTest {
   }
 
   /**
-   * Proves the accept side of the expansion ceiling: content that expands to exactly
-   * the ceiling installs, so the boundary is exclusive of failure.
+   * Proves the accept side of the expansion ceiling: a gzip stream that expands to
+   * exactly the ceiling installs, so the boundary is exclusive of failure.
    */
   @Test
   void testExpansionExactlyAtCeilingSucceeds(@TempDir Path source, @TempDir Path target)
@@ -694,7 +715,8 @@ public class ResourceInstallerTest {
     final Path file = source.resolve("exact.tar.gz");
     Files.write(file, gzip(tar.toByteArray()));
 
-    ResourceInstaller.install(file.toUri(), target, null, ceilings(MEBIBYTE, KIBIBYTE));
+    ResourceInstaller.install(file.toUri(), target, null,
+        ceilings(MEBIBYTE, tar.size()));
 
     Assertions.assertEquals(List.of("corpus/exact.bin"), installedFiles(target));
     Assertions.assertEquals(1024, Files.size(target.resolve("corpus/exact.bin")));
diff --git a/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/archive/TarStreamTest.java b/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/archive/TarStreamTest.java
index a7e2aa0d8..4d9f5be32 100644
--- a/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/archive/TarStreamTest.java
+++ b/opennlp-core/opennlp-runtime/src/test/java/opennlp/tools/util/archive/TarStreamTest.java
@@ -367,9 +367,6 @@ public class TarStreamTest {
     Assertions.assertTrue(stream.next());
     Assertions.assertEquals("plain.txt", stream.name());
   }
-
-
-
   /**
    * Proves that a pax global header carrying only a {@code comment} record is consumed
    * and the entry after it is delivered normally. A tar written by {@code git archive}
@@ -379,8 +376,7 @@ public class TarStreamTest {
   void testPaxGlobalHeaderWithOnlyACommentIsConsumed() throws IOException {
     final ByteArrayOutputStream tar = new ByteArrayOutputStream();
     entry(tar, "pax_global_header",
-        concat(TarArchives.paxRecord("comment", "0123456789abcdef"),
-            metadataRecords()), 'g');
+        TarArchives.paxRecord("comment", "0123456789abcdef"), 'g');
     entry(tar, "data.txt", "content".getBytes(StandardCharsets.UTF_8));
     tar.write(new byte[TERMINATOR_SIZE]);
     final TarStream stream = new TarStream(new ByteArrayInputStream(tar.toByteArray()));
@@ -793,7 +789,9 @@ public class TarStreamTest {
 
   /**
    * Proves that the largest length a {@code long} can hold round-trips, so the overflow
-   * guard rejects only what genuinely does not fit.
+   * guard rejects only what genuinely does not fit. Advancing afterward must still
+   * detect that the declared content is absent rather than overflowing the skip count
+   * and reporting a clean end of archive.
    */
   @Test
   void testBase256SizeFieldAcceptsTheLargestRepresentableLength() throws IOException {
@@ -802,6 +800,8 @@ public class TarStreamTest {
 
     Assertions.assertTrue(stream.next());
     Assertions.assertEquals(Long.MAX_VALUE, stream.size());
+    final IOException thrown = Assertions.assertThrows(IOException.class, stream::next);
+    Assertions.assertEquals("truncated tar archive", thrown.getMessage());
   }
 
   /**