This is an automated email from the ASF dual-hosted git repository.
tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/main by this push:
new ebf458feec TIKA-5060: turn off ocr if tesseract is on the path for
fuzzing (#3597)
ebf458feec is described below
commit ebf458feec8f489d85afd78b84b8608d7430aff7
Author: Tim Allison <[email protected]>
AuthorDate: Mon Nov 9 17:11:52 2026 -0500
TIKA-5060: turn off ocr if tesseract is on the path for fuzzing (#3597)
* TIKA-5060: tika.fuzz.config for the Jazzer harness; config to turn OCR off
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.skills/devs/oss-fuzz/SKILL.md | 9 ++++++---
AGENTS.md | 2 +-
tika-fuzzing/README.md | 10 ++++++++++
tika-fuzzing/pom.xml | 6 ++++++
.../tika/fuzzing/AutoDetectParserFuzzTest.java | 20 ++++++++++++++++++--
.../src/test/resources/tika-config-no-ocr.json | 5 +++++
6 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/.skills/devs/oss-fuzz/SKILL.md b/.skills/devs/oss-fuzz/SKILL.md
index 528daf7945..d34512f3b9 100644
--- a/.skills/devs/oss-fuzz/SKILL.md
+++ b/.skills/devs/oss-fuzz/SKILL.md
@@ -31,12 +31,15 @@ read after this file, wins on conflict.
# Tika OSS-Fuzz — local fuzzing
For fuzzing or replaying a directory of files without Docker, use the in-repo
-`tika-fuzzing` module (Jazzer `@FuzzTest`, see `tika-fuzzing/README.md`). This
skill
+`tika-fuzzing` module (Jazzer `@FuzzTest`, see `tika-fuzzing/README.md`). On a
host with
+Tesseract installed, pass
`-Dtika.fuzz.config=src/test/resources/tika-config-no-ocr.json`:
+otherwise every embedded image is OCR'd and parses time out falsely. This skill
covers the OSS-Fuzz project, whose targets still live in the oss-fuzz repo.
Tika is already in OSS-Fuzz as the **`apache-tika`** project (not `tika`).
-It is Jazzer-based (coverage-guided, in-process JVM fuzzing), not the old
-`tika-fuzzing` seed-mutation module (removed in TIKA-4506). The fuzz targets
+It is Jazzer-based (coverage-guided, in-process JVM fuzzing), like today's
+`tika-fuzzing` module; the older seed-mutation module of that name was removed
in
+TIKA-4506. The fuzz targets
and seed logic live in the **oss-fuzz** repo under
`projects/apache-tika/`, *not* in this repo:
diff --git a/AGENTS.md b/AGENTS.md
index 22febb6ef2..e066d5e642 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -49,7 +49,7 @@ Contributor-facing — building, testing, and releasing this
codebase.
| `.skills/devs/tika-eval-encoding-regression/SKILL.md` | Charset-detector
regression hunts |
| `.skills/devs/tika-eval-h2-query/SKILL.md` | Querying the tika-eval H2
database directly |
| `.skills/devs/update-site-for-release/SKILL.md` | Updating tika.apache.org
for a release |
-| `.skills/devs/oss-fuzz/SKILL.md` | Fuzzing a parser locally (OSS-Fuzz Jazzer
targets); reproducing an OSS-Fuzz crash |
+| `.skills/devs/oss-fuzz/SKILL.md` | Fuzzing a parser locally (in-repo
`tika-fuzzing` module, or OSS-Fuzz Jazzer targets); reproducing an OSS-Fuzz
crash |
## Using Tika
diff --git a/tika-fuzzing/README.md b/tika-fuzzing/README.md
index 99f187b1a6..882c31062d 100644
--- a/tika-fuzzing/README.md
+++ b/tika-fuzzing/README.md
@@ -32,11 +32,21 @@ The targets look for OOM, stack overflow, hangs, and
exceptions other than
|---|---|---|
| `-Dtika.fuzz.timeout=<s>` | `60` | per-input parse timeout, all modes; a
hang is reported with the stuck stack |
| `-Dtika.fuzz.xmx=<size>` | `3g` | test JVM heap (OSS-Fuzz uses `-Xmx3000m`) |
+| `-Dtika.fuzz.config=<path>` | none | Tika JSON config for the parser, e.g.
to turn OCR off |
| `JAZZER_MAX_DURATION=<d>` | Jazzer's | length of a fuzzing session |
Do not use JUnit's `junit.jupiter.execution.timeout.*`: in fuzzing mode it
ends the
whole session, not one input.
+## Tesseract
+
+If `tesseract` is on the PATH, Tika runs OCR on every image it meets, embedded
ones
+included. OCR is an external process: Jazzer gets no coverage from it, and it
makes parses
+slow enough to time out. A timed-out parse cannot be stopped, so its OCR keeps
running and
+later inputs time out too. OSS-Fuzz images have no Tesseract. Turn OCR off in
every mode
+below with `-Dtika.fuzz.config=src/test/resources/tika-config-no-ocr.json`
(relative to
+this module, where the tests run).
+
## Regression mode (every build)
`./mvnw clean test -pl tika-fuzzing` replays each method's inputs from
diff --git a/tika-fuzzing/pom.xml b/tika-fuzzing/pom.xml
index b84f7c136e..629a9d25f3 100644
--- a/tika-fuzzing/pom.xml
+++ b/tika-fuzzing/pom.xml
@@ -53,6 +53,12 @@
<type>pom</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-serialization</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>tika-parser-sqlite3-module</artifactId>
diff --git
a/tika-fuzzing/src/test/java/org/apache/tika/fuzzing/AutoDetectParserFuzzTest.java
b/tika-fuzzing/src/test/java/org/apache/tika/fuzzing/AutoDetectParserFuzzTest.java
index c1cc4beea2..bcc372fa1f 100644
---
a/tika-fuzzing/src/test/java/org/apache/tika/fuzzing/AutoDetectParserFuzzTest.java
+++
b/tika-fuzzing/src/test/java/org/apache/tika/fuzzing/AutoDetectParserFuzzTest.java
@@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -30,6 +31,7 @@ import java.util.concurrent.TimeoutException;
import com.code_intelligence.jazzer.junit.FuzzTest;
import org.xml.sax.SAXException;
+import org.apache.tika.config.loader.TikaLoader;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -45,17 +47,31 @@ import org.apache.tika.sax.RecursiveParserWrapperHandler;
* (OOM, stack overflow), hangs, and anything not a
TikaException/IOException/SAXException.
* With {@code -Dtika.fuzz.strict=true}, a parser RuntimeException that
CompositeParser
* wrapped in a TikaException is a finding too. A parse longer than {@code
tika.fuzz.timeout}
- * seconds (default 60) is reported with the stuck thread's stack.
+ * seconds (default 60) is reported with the stuck thread's stack. {@code
-Dtika.fuzz.config}
+ * names a Tika JSON config to build the parser from.
*/
class AutoDetectParserFuzzTest {
- private static final Parser PARSER = new RecursiveParserWrapper(new
AutoDetectParser());
+ private static final Parser PARSER = new
RecursiveParserWrapper(autoDetectParser());
private static final boolean STRICT =
Boolean.getBoolean("tika.fuzz.strict");
private static final long TIMEOUT_SECONDS =
Long.getLong("tika.fuzz.timeout", 60);
private static ExecutorService worker;
private static volatile Thread workerThread;
+ /** @return the AutoDetectParser from {@code -Dtika.fuzz.config}, or the
default one */
+ private static Parser autoDetectParser() {
+ String config = System.getProperty("tika.fuzz.config");
+ if (config == null || config.isBlank()) {
+ return new AutoDetectParser();
+ }
+ try {
+ return TikaLoader.load(Paths.get(config)).loadAutoDetectParser();
+ } catch (TikaException | IOException e) {
+ throw new IllegalStateException("cannot load tika.fuzz.config " +
config, e);
+ }
+ }
+
@FuzzTest
void bytes(byte[] data) throws Exception {
try (TikaInputStream tis = TikaInputStream.get(data)) {
diff --git a/tika-fuzzing/src/test/resources/tika-config-no-ocr.json
b/tika-fuzzing/src/test/resources/tika-config-no-ocr.json
new file mode 100644
index 0000000000..9e8f0b3f2f
--- /dev/null
+++ b/tika-fuzzing/src/test/resources/tika-config-no-ocr.json
@@ -0,0 +1,5 @@
+{
+ "text-recognizers": [
+ { "tesseract-ocr-parser": { "skipOcr": true } }
+ ]
+}