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 8c41a35d7a TIKA-4957: no spurious EOFException warning on well-formed
MP4 files (#3304)
8c41a35d7a is described below
commit 8c41a35d7ac60d0ca1a0853827edaec62cc8f3ac
Author: Tim Allison <[email protected]>
AuthorDate: Wed Oct 7 12:02:16 2026 -0400
TIKA-4957: no spurious EOFException warning on well-formed MP4 files (#3304)
---
CHANGES.txt | 5 +++++
.../java/org/apache/tika/parser/mp4/TikaMp4Reader.java | 7 +++++++
.../apache/tika/parser/mp4/boxes/TikaUserDataBox.java | 3 ++-
.../java/org/apache/tika/parser/mp4/MP4ParserTest.java | 17 +++++++++++++++++
4 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 5a2ece3ec1..b73770dcf8 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -80,6 +80,11 @@ Release 4.2.0 - unreleased
Metadata, InputStream, byte[]) is deprecated in favour of the overload
that takes a ParseContext (TIKA-4936).
+ * The MP4 parser no longer records a spurious EOFException warning on every
+ well-formed file: end of input at a top-level box boundary is the normal
+ exit, and the ilst length no longer counts its own header twice. Since
+ 4.0.0 (TIKA-4957).
+
* tika-core's OSGi manifest no longer requires a Service Loader Mediator or
providers for Parser, Detector, EncodingDetector, LanguageDetector and
MetadataFilter; 4.1.0 failed to install on its own in Equinox/p2
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/TikaMp4Reader.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/TikaMp4Reader.java
index df31145868..9ae6aada6b 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/TikaMp4Reader.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/TikaMp4Reader.java
@@ -16,6 +16,7 @@
*/
package org.apache.tika.parser.mp4;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -73,8 +74,10 @@ final class TikaMp4Reader {
handler.addError("MP4 box nesting exceeds the maximum depth of " +
MAX_BOX_DEPTH);
return;
}
+ long boxStart = reader.getPosition();
try {
while (atomEnd == -1 || reader.getPosition() < atomEnd) {
+ boxStart = reader.getPosition();
long boxSize = reader.getUInt32();
String boxType = reader.getString(4);
//4 bytes size + 4 bytes type, plus 8 more when a 64-bit
largesize follows
@@ -121,6 +124,10 @@ final class TikaMp4Reader {
}
}
} catch (IOException e) {
+ if (atomEnd == -1 && e instanceof EOFException &&
reader.getPosition() == boxStart) {
+ //the top level ends at end of input: no bytes of a next box
were read
+ return;
+ }
//not handler.addError: the library's error strings bypass the
reporting policy
EmbeddedDocumentUtil.recordException(e, metadata, parseContext);
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/boxes/TikaUserDataBox.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/boxes/TikaUserDataBox.java
index 5829b4ea66..c95905805b 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/boxes/TikaUserDataBox.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/boxes/TikaUserDataBox.java
@@ -151,7 +151,8 @@ public class TikaUserDataBox {
if (len < 8L || len >= Integer.MAX_VALUE) {
throw new IOException("Malformed ilst length in udta metadata: " +
len);
}
- processIList(reader, len);
+ //len includes the 8-byte ilst header already read above
+ processIList(reader, len - 8);
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp4/MP4ParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp4/MP4ParserTest.java
index 11fbf1bf57..3a78d71e53 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp4/MP4ParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp4/MP4ParserTest.java
@@ -253,6 +253,23 @@ public class MP4ParserTest extends TikaTest {
assertEquals("mp4a", r.metadata.get(Audio.FOURCC));
}
+ /**
+ * End of input at a top-level box boundary is the normal exit, not a
warning, and
+ * the ilst length includes its own header, which must not be read again
as a
+ * record. Both used to put an EOFException warning on every well-formed
file.
+ */
+ @Test
+ public void testWellFormedFilesHaveNoWarning() throws Exception {
+ for (String name : new String[]{"testMP4.m4a", "testMP4AudioOnly.mp4",
+ "testMP4VideoAudio.mp4", "testMP4_coverArt.m4a",
"testMP4_twoCovers.m4a",
+ "testMP4_encv.mp4", "testMP4_drm.m4a", "testMP4_drm_frma.m4a",
+ "testMP4_esdsFlags.m4a", "testMP4_twoSampleEntries.m4a"}) {
+ String[] warnings = getXML(name).metadata
+ .getValues(TikaCoreProperties.TIKA_META_EXCEPTION_WARNING);
+ assertEquals(0, warnings.length, name + ": " +
Arrays.toString(warnings));
+ }
+ }
+
@Test
@Timeout(30000)
public void testInfiniteLoop() throws Exception {