Repository navigation
PSD: a memory budget for one decode and a capped smart-object bake (#1138) - #1139
Merged
h-a-n-a-s-h-i merged 1 commit intoOct 13, 2026
Merged
Conversation
…torytold#1138) The 2^28 pixel limit applied per image; one composite or layer decode kept the ZIP output, a Vec<f32> per channel and the result alive together, and the bake size came from the file's quad. A decode now charges every buffer against a byte budget (4 GiB, 1 GiB on 32-bit), checks its whole expected peak before allocating, writes channels straight into the result and returns an error when over budget. Bakes are at most 4x the document across and 2^24 pixels. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
h-a-n-a-s-h-i
pushed a commit
that referenced
this pull request
Oct 13, 2026
Member
|
Merged. Thank you for the contribution, @vangel76! It landed on |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1138
Cause
MAX_DECODE_PIXELS(2^28) bounded one decoded image only.composite()kept the ZIP output (want * rowbytes * h), oneVec<f32>per channel and the resultVec<[f32; 4]>alive together,layer_pixels()the channel planes, alpha, mask and output. A 16384 x 16384 header with a small ZIP stream of zeros therefore asked for roughly 10-14 GiB (an uncatchable abort), and on wasm32vec![[0f32; 4]; n]panics with a capacity overflow for n >= 2^27. The smart-object bake size came from the file: a quad corner of 1e6 gaveneeds_bakeand a 16384 x 16384 (4 GiB) bake.Change
crates/psd/src/lib.rs: aBudget(4 GiB; 1 GiB undertarget_pointer_width = "32") that every buffer of one decode is charged against.composite()andlayer_pixels()first check their whole expected peak (result at 16 bytes a pixel, CMYK black plate, the channel or ZIP buffer, the mask) and returnError::Unsupported("... over the N MiB memory budget")before allocating anything. Allocation goes throughtry_reserve_exact, notvec![..; n]. The ZIP limit is the size the channels need.Vec<f32>per channel, no second result; audit item O4). The CMYK black plate is the only extra float plane.crates/psd/src/placed.rs:SmartObject::bake_scale(w, h, k, doc)lowerskso a bake is at most 4x the document across either way and at mostMAX_BAKE_PIXELS(2^24);render_placedreturnsNonefor an output over the cap and reserves withtry_reserve_exact.crates/engine/src/psd_import.rsusesbake_scale. Interpretation of "4x the document": 4x per side, not 4x area.MediaError::Decodemapping inmedia/layered.rs, an ordinary decode error.Tests (
crates/psd/src/memory_tests.rs,placed.rs)render_placedrefuses a 16384 x 16384 output.The budget and bake tests use new APIs (
composite_with_budget,bake_scale) and do not compile onmain; I did not run the huge-header test against the old code (it would allocate GiBs).Commands run
cargo test -p effectcraft-psd(22 passed),cargo test -p effectcraft-engine --lib(546 passed),cargo test -p effectcraft-media,cargo test -p effectcraft-script,cargo test -p effectcraft-host --test vector_importcargo clippy --workspace --all-targets -- -D warnings,cargo fmt --all --check,cargo xtask layerscargo check --target wasm32-unknown-unknown -p effectcraft-psd -p effectcraft-media -p effectcraft-engineNot run:
cargo xtask cias a whole, the full workspace test suite (including ui-egui), real Photoshop files from the corpus.Deliberately left out
commands/file.rs,footage_reload.rs,media/layered.rs): those files are touched by feat(import): import an EffectCraft project into the open project (file.importProject) #1104/Refresh layered composition sources on import #1087/#1070: a fresh import or opened project reads overwritten footage again #1086/feat(aep): import After Effects projects through an external py-aep converter #860/perf: faster effects, expressions, text, caches, movie reading, project open, export and UI playback #856; the library now refuses on its own.media/layered.rs(load_oriented) is unchanged.Expect small conflicts in
crates/psd/src/lib.rswith the parallel PSD PRs (#1137, #1134, #1131, #1129); I will mergeupstream/mainafter they land.🤖 Generated with Claude Code