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 {

Reply via email to