{"record":{"id":"ee5fe548786e4bf5","repo":"TeamNewPipe/NewPipe","slug":"trun-box-has-wrong-data-offset-points-outside-of","errorCode":null,"errorMessage":"trun box has wrong data offset, points outside of concurrent mdat box","messagePattern":"trun box has wrong data offset, points outside of concurrent mdat box","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java","lineNumber":204,"sourceCode":"                box = readBox();\n            } else {\n                chunkZero = true;\n            }\n\n            switch (box.type) {\n                case ATOM_MOOF:\n                    if (moof != null) {\n                        throw new IOException(\"moof found without mdat\");\n                    }\n\n                    moof = parseMoof(box, track.trak.tkhd.trackId);\n\n                    if (moof.traf != null) {\n\n                        if (hasFlag(moof.traf.trun.bFlags, 0x0001)) {\n                            moof.traf.trun.dataOffset -= box.size + 8;\n                            if (moof.traf.trun.dataOffset < 0) {\n                                throw new IOException(\"trun box has wrong data offset, \"\n                                        + \"points outside of concurrent mdat box\");\n                            }\n                        }\n\n                        if (moof.traf.trun.chunkSize < 1) {\n                            if (hasFlag(moof.traf.tfhd.bFlags, 0x10)) {\n                                moof.traf.trun.chunkSize = moof.traf.tfhd.defaultSampleSize\n                                        * moof.traf.trun.entryCount;\n                            } else {\n                                moof.traf.trun.chunkSize = (int) (box.size - 8);\n                            }\n                        }\n                        if (!hasFlag(moof.traf.trun.bFlags, 0x900)\n                                && moof.traf.trun.chunkDuration == 0) {\n                            if (hasFlag(moof.traf.tfhd.bFlags, 0x20)) {\n                                moof.traf.trun.chunkDuration = moof.traf.tfhd.defaultSampleDuration\n                                        * moof.traf.trun.entryCount;\n                            }","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/TeamNewPipe/NewPipe/blob/9e8be091560a69f35d44bd252eb00bc7911c977b/app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java#L186-L222","documentation":"In nextChunk(), after parsing a moof the reader adjusts trun.dataOffset by subtracting (box.size + 8) to convert it into a relative offset. If the result is negative, the trun's declared data offset points before the start of the current mdat — an impossible/invalid value. The IOException catches malformed or maliciously crafted fragment headers that would misdirect sample reads.","triggerScenarios":"A moof whose trun box has the data-offset-present flag (0x0001) set but whose dataOffset value is smaller than (moof box size + 8), yielding a negative relative offset. Caused by a corrupt or hand-crafted trun box.","commonSituations":"A malformed fragment produced by a broken server-side packager; a file edited/tampered with; a partial download that corrupted the trun header fields.","solutions":["Re-download the segment; the trun header is internally inconsistent and cannot be trusted.","Re-mux with a conformant MP4 muxer to regenerate correct trun data offsets.","Validate fragments with an MP4 conformance tool before demuxing.","If you control muxing, ensure trun.dataOffset is set to the absolute position of the first sample relative to the file, never to a value smaller than the moof header extent."],"exampleFix":"// before — muxer writes raw trun.dataOffset without accounting for box header\ntrun.dataOffset = samplesStart;\n\n// after — set absolute offset from start of file (moof header size included)\ntrun.dataOffset = moofFileOffset + moofHeaderSize + samplesStart;","handlingStrategy":"validation","validationCode":"// Validate the trun dataOffset is internally consistent before relying on it.\n// This is a producer-side check; consumers cannot repair a bad offset.\n// When muxing: ensure trun.dataOffset >= (moofBoxSize + 8).","typeGuard":"public static boolean trunDataOffsetValid(long dataOffset, long moofBoxSize) {\n    return (dataOffset - (moofBoxSize + 8)) >= 0;\n}","tryCatchPattern":"try {\n    chunk = reader.getNextChunk(false);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"data offset\")) {\n        // fragment has an invalid trun offset — skip this fragment, try the next\n        Log.w(TAG, \"bad trun offset, skipping fragment\");\n        continue;\n    } else throw e;\n}","preventionTips":["Re-download fragments whose trun offsets are inconsistent.","When muxing, compute trun.dataOffset as an absolute file position.","Validate fragments with MP4Box conformance checks.","Do not trust hand-edited MP4 files."],"tags":["mp4","dash","corrupt-data","offset-validation","java"],"backgroundTag":null,"analyzedSha":"9e8be091560a69f35d44bd252eb00bc7911c977b","analyzedAt":"2026-08-14T00:11:33.519Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}