R5 — Media3Engine builds EditedMediaItem/Composition unguarded on the HandlerThread; a picker-reachable spec throws there #14

Closed
opened 2026-08-23 03:44:43 +00:00 by JMR-dev · 0 comments
JMR-dev commented 2026-08-23 03:44:43 +00:00 (Migrated from github.com)

Finding R5 from the overnight max-effort review (Fable lead, Opus sub-agents). Full report: scratchpad/overnight/REVIEW.md.

R5 — Media3Engine builds EditedMediaItem/Composition unguarded on the HandlerThread; a picker-reachable spec throws there

severity: medium
verdict: CONFIRMED (reachability demonstrated on the JVM; process-death consequence read, not executed)
where: app/src/main/java/org/libremediaconverter/convert/Media3Engine.kt:80-90 (file unchanged tonight; this answers the audit's own D14 open question about the other native boundaries)
scenario: Audio-only input (MP3) + Advanced picker Container=MP4, Video=H.265, Audio=NONE: CopyPlanner yields (Drop, Drop); ContainerCapabilities.validate says Valid (the COPY form is correctly rejected, the H264/H265 form is not); router sends it to MEDIA3. EditedMediaItem's constructor checkState("Audio and video cannot both be removed") throws IllegalStateException at :83 — on the media3-transformer HandlerThread, outside both runCatching blocks, invisible to the worker's catch(Throwable) and leaving the continuation permanently unresumed; an uncaught handler-thread exception kills the process.
evidence: JVM probe in reviewer clone: plan=(Drop,Drop), validation=Valid, engine=MEDIA3 for H265+NONE and H264+NONE; Invalid for COPY+NONE. checkState read from media3-transformer-1.11.0-sources.jar EditedMediaItem.java:368-369. Lead re-read Media3Engine.kt:71-100 and confirmed lines 80-90 sit between the two runCatching blocks. FFmpegEngine and ConcatEngine checked clean (every call inside worker catch(Throwable), including FFmpegEngine's init).
fix: Widen the existing runCatching to cover the builders (backstop). Separately decide whether validate() should reject encode-video-into-a-file-with-no-video-track as it already does for COPY — that is the real defect.
risk: Guard-widening is behaviour-neutral on success. The validation change newly refuses a picker-enabled combination -> needs its own test. Plan/validate/route chain is JVM-testable; the actual throw needs an instrumented test.


Cut: below — held for manual review: product decision, CI/workflow, hardware, or PLAUSIBLE verdict.

🤖 Generated with Claude Code

_Finding **R5** from the overnight max-effort review (Fable lead, Opus sub-agents). Full report: `scratchpad/overnight/REVIEW.md`._ ### R5 — Media3Engine builds EditedMediaItem/Composition unguarded on the HandlerThread; a picker-reachable spec throws there severity: medium verdict: CONFIRMED (reachability demonstrated on the JVM; process-death consequence read, not executed) where: app/src/main/java/org/libremediaconverter/convert/Media3Engine.kt:80-90 (file unchanged tonight; this answers the audit's own D14 open question about the other native boundaries) scenario: Audio-only input (MP3) + Advanced picker Container=MP4, Video=H.265, Audio=NONE: CopyPlanner yields (Drop, Drop); ContainerCapabilities.validate says Valid (the COPY form is correctly rejected, the H264/H265 form is not); router sends it to MEDIA3. EditedMediaItem's constructor checkState("Audio and video cannot both be removed") throws IllegalStateException at :83 — on the media3-transformer HandlerThread, outside both runCatching blocks, invisible to the worker's catch(Throwable) and leaving the continuation permanently unresumed; an uncaught handler-thread exception kills the process. evidence: JVM probe in reviewer clone: plan=(Drop,Drop), validation=Valid, engine=MEDIA3 for H265+NONE and H264+NONE; Invalid for COPY+NONE. checkState read from media3-transformer-1.11.0-sources.jar EditedMediaItem.java:368-369. Lead re-read Media3Engine.kt:71-100 and confirmed lines 80-90 sit between the two runCatching blocks. FFmpegEngine and ConcatEngine checked clean (every call inside worker catch(Throwable), including FFmpegEngine's init). fix: Widen the existing runCatching to cover the builders (backstop). Separately decide whether validate() should reject encode-video-into-a-file-with-no-video-track as it already does for COPY — that is the real defect. risk: Guard-widening is behaviour-neutral on success. The validation change newly refuses a picker-enabled combination -> needs its own test. Plan/validate/route chain is JVM-testable; the actual throw needs an instrumented test. --- **Cut:** `below` — held for manual review: product decision, CI/workflow, hardware, or PLAUSIBLE verdict. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMediaConverter#14