Skip to content

fix(desktop): GIF decode memory budget must include logical compositing buffers#15

Draft
cursor[bot] wants to merge 1 commit into
windows-experimentalfrom
cursor/critical-bug-investigation-08ed
Draft

fix(desktop): GIF decode memory budget must include logical compositing buffers#15
cursor[bot] wants to merge 1 commit into
windows-experimentalfrom
cursor/critical-bug-investigation-08ed

Conversation

@cursor

@cursor cursor Bot commented May 27, 2026

Copy link
Copy Markdown

Summary

Fixes a memory-limit bypass in desktop GIF decoding: the decode budget previously counted only output-frame pixels, while compositing allocates two full logical-screen BufferedImages. Large logical dimensions with a small on-card target could pass the check and still allocate very large working buffers (risk of OOM / process kill).

PR type

  • Bug fix

Why

Regression risk from commit 7bb656d3 (fix(desktop): sharpen posters and stabilize GIF render), which composes GIF frames in logical space before scaling. The guard approxBytes > MaxDecodedGifBytes no longer reflected peak decode memory because logicalCanvas and previousLogicalCanvas are baseW × baseH each.

Concrete scenario: GIF with logical screen 3000×3000 (within MaxLogicalGifPixels), shown in a small collection card so canvasW/canvasH are ~200×200 and frameCount × output bytes stays under 64 MiB, but 2 × 3000 × 3000 × 4 ≈ 68 MiB is allocated before counting frame bitmaps—exceeding the intended cap and risking OOM. The app then falls back to static Coil only if decode completes without exhausting memory; the failure mode is worse under memory pressure.

Policy check

  • This PR is not cosmetic-only, unless it is a translation PR.
  • This PR does not add a new major feature without prior approval.
  • This PR is small in scope and focused on one problem.
  • If this is a larger or directional change, I linked the approved feature request issue below.

Testing

  • ./gradlew :composeApp:compileKotlinDesktop was attempted; build failed in this environment due to unresolved dependency org.openani.mediamp:mediamp-mpv:0.1.0-dev-1 (classpath), not due to this change.
  • read_lints on the edited file: no issues.

Screenshots / Video (UI changes only)

N/A

Breaking changes

None. Some very large logical-dimension GIFs that previously attempted decode may now bail earlier and use the existing static Coil fallback (same as other decode failures).

Linked issues

N/A (automation / critical bug sweep).

Open in Web View Automation 

decodeGifForCompose composes on two full logical-screen BufferedImages.
The existing guard only counted output-frame bytes, so a large logical
size with a small on-card target passed the check while allocating tens
of megabytes in working buffers, risking OOM. Reject early when logical
working memory plus retained frames exceeds MaxDecodedGifBytes.

Co-authored-by: Fab <CreepsoOff@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant