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());
}
/**