This is an automated email from the ASF dual-hosted git repository.
tballison pushed a commit to branch branch_3x
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/branch_3x by this push:
new fa1f055a88 TIKA-4761 - improve sevenz memory limits
fa1f055a88 is described below
commit fa1f055a88b147e1cd29e01618796a30814367d0
Author: tallison <[email protected]>
AuthorDate: Thu Jun 25 11:50:40 2026 -0400
TIKA-4761 - improve sevenz memory limits
---
.../org/apache/tika/parser/pkg/PackageParser.java | 27 +++++++++++++++++++++-
.../apache/tika/parser/pkg/Seven7ParserTest.java | 18 +++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
index f596828fa8..8db2714264 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
@@ -38,6 +38,7 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
+import org.apache.commons.compress.MemoryLimitException;
import org.apache.commons.compress.PasswordRequiredException;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
@@ -65,6 +66,7 @@ import org.apache.tika.config.Field;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
+import org.apache.tika.exception.TikaMemoryLimitException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
import org.apache.tika.io.TemporaryResources;
@@ -235,6 +237,7 @@ public class PackageParser extends
AbstractEncodingDetectorParser {
}
private boolean detectCharsetsInEntryNames = true;
+ private int memoryLimitInKb = 100000;
public PackageParser() {
super();
@@ -312,7 +315,9 @@ public class PackageParser extends
AbstractEncodingDetectorParser {
SevenZFile sevenz;
try {
- SevenZFile.Builder builder = new
SevenZFile.Builder().setFile(tstream.getFile());
+ // Use setMaxMemoryLimitKiB (direct KiB);
setMaxMemoryLimitKb divides by 1024.
+ SevenZFile.Builder builder = new
SevenZFile.Builder().setFile(tstream.getFile())
+ .setMaxMemoryLimitKiB(memoryLimitInKb);
if (password == null) {
sevenz = builder.get();
} else {
@@ -320,6 +325,8 @@ public class PackageParser extends
AbstractEncodingDetectorParser {
}
} catch (PasswordRequiredException e) {
throw new EncryptedDocumentException(e);
+ } catch (MemoryLimitException e) {
+ throw new TikaMemoryLimitException(e.getMessage());
}
// Pending a fix for COMPRESS-269 / TIKA-1525, this bit is a
little nasty
@@ -359,6 +366,8 @@ public class PackageParser extends
AbstractEncodingDetectorParser {
true);
parseEntries(ais, metadata, extractor, xhtml, true, entryCnt);
}
+ } catch (MemoryLimitException e) {
+ throw new TikaMemoryLimitException(e.getMessage());
} finally {
ais.close();
tmp.close();
@@ -662,4 +671,20 @@ public class PackageParser extends
AbstractEncodingDetectorParser {
public boolean isDetectCharsetsInEntryNames() {
return detectCharsetsInEntryNames;
}
+
+ /**
+ * Maximum memory in kibibytes to allow for LZMA/LZMA2 dictionary
allocation when parsing
+ * 7z archives. A tiny crafted 7z can declare a multi-GiB dictionary in a
single header byte;
+ * this caps it so commons-compress throws a MemoryLimitException instead
of OOMing the parser.
+ *
+ * @param memoryLimitInKb
+ */
+ @Field
+ public void setMemoryLimitInKb(int memoryLimitInKb) {
+ this.memoryLimitInKb = memoryLimitInKb;
+ }
+
+ public int getMemoryLimitInKb() {
+ return memoryLimitInKb;
+ }
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/test/java/org/apache/tika/parser/pkg/Seven7ParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/test/java/org/apache/tika/parser/pkg/Seven7ParserTest.java
index 1afce70fbd..d53a93e966 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/test/java/org/apache/tika/parser/pkg/Seven7ParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/test/java/org/apache/tika/parser/pkg/Seven7ParserTest.java
@@ -19,6 +19,7 @@ package org.apache.tika.parser.pkg;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.InputStream;
@@ -26,7 +27,9 @@ import java.io.InputStream;
import org.junit.jupiter.api.Test;
import org.xml.sax.ContentHandler;
+import org.apache.tika.exception.TikaMemoryLimitException;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
/**
@@ -72,4 +75,19 @@ public class Seven7ParserTest extends AbstractPkgTest {
assertTrue(mod.startsWith("20"), "Modified at " + mod);
}
}
+
+ /**
+ * A 7z whose declared LZMA2 dictionary exceeds the configured limit must
fail with a
+ * {@link TikaMemoryLimitException} rather than eagerly allocating the
dictionary (which a
+ * tiny crafted 7z can drive to multiple GiB, OOMing the parser).
+ */
+ @Test
+ public void testMemoryLimit() throws Exception {
+ PackageParser parser = new PackageParser();
+ parser.setMemoryLimitInKb(1); // 1 KiB, smaller than any real LZMA2
dictionary
+ try (InputStream stream =
getResourceAsStream("/test-documents/test-documents.7z")) {
+ assertThrows(TikaMemoryLimitException.class, () ->
parser.parse(stream,
+ new BodyContentHandler(), new Metadata(), new
ParseContext()));
+ }
+ }
}