Commit Graph
5366 Commits
Author SHA1 Message Date
Brandon ThomasandClaude Opus 5.5 4991f6377e packaging(macos): retry stapling when Apple's ticket lookup drops (#8995)
* packaging(macos): retry stapling when Apple's ticket lookup drops

The 0.15.0 release's macOS job failed after both notarizations were
accepted: stapling the DMG lost its connection to Apple's CloudKit
ticket service (error 68). Retry stapling up to five times with a
growing pause before failing the job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* packaging(macos): retry stapler validation too

The re-run of the 0.15.0 macOS job stapled the DMG, then lost the
CloudKit connection in `stapler validate` (error 68 again). Retry
staple + validate as a pair in package.sh, and retry the validation
verify.sh does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:11:00 -04:00
Dylan M. Taylor 6d4b9690ab deps: roxmltree 0.21 in photocraft-io and photocraft-engine (#8973) 2026-10-23 17:06:29 -04:00
Dylan M. Taylor ed67aa5859 Merge pull request #8990 from dylanmtaylor/ci/sonar-main-not-cancelled
ci(sonar): stop cancelling main-branch runs so coverage is published
2026-10-23 17:05:16 -04:00
Dylan M. Taylor 5521968828 ci(sonar): don't cancel superseded runs on main, so coverage is published 2026-10-23 16:47:12 -04:00
aiongg 84a2aa9b03 Merge pull request #8980 from aiongg/panic-hunt-fallback-heif
xtask: the panic hunt without nextest builds with the HEIF decoder
2026-10-23 16:36:09 -04:00
aiongg 8debb6c420 xtask: the panic hunt without nextest builds with the HEIF decoder 2026-10-23 20:10:26 +00:00
aiongg bde136874f Merge pull request #8970 from aiongg/xtask-ci-gate
CI: cargo xtask ci is the gate, and the workflow runs it
2026-10-23 16:07:24 -04:00
Dylan M. Taylor f3f2acc5ec Merge pull request #8960 from dylanmtaylor/security/gpu-plan-and-ui-swatch
security(gpu,ui-egui): bound clipped group planning; pattern swatch sampling
2026-10-23 15:52:58 -04:00
Dylan M. Taylor 597ea53023 Merge pull request #8958 from dylanmtaylor/security/plugins-host-hardening
security(plugins): host keys, band count, start fuel, FIFO open
2026-10-23 15:52:53 -04:00
Dylan M. Taylor 697aaf3f49 Merge pull request #8947 from dylanmtaylor/security/codecs-truncated-scan-icc
security(codecs): bound truncated JPEG recovery; count WebP frame ICC copies
2026-10-23 15:52:48 -04:00
aiongg 4b51647955 Merge remote-tracking branch 'upstream/main' into xtask-ci-gate
# Conflicts:
#	xtask/src/main.rs
2026-10-23 19:44:29 +00:00
aiongg 1ecb61db42 Merge pull request #8964 from aiongg/translation-gaps-pass
Tests: missing translations don't fail; xtask ci lists them
2026-10-23 15:43:33 -04:00
Dylan M. Taylor 6ca5bf359d security(compose): bound dense working sets and nested Blend If evaluation (#8949)
* security(compose): bound dense working sets and repeated group evaluation

Smart-filter mixing and stroke fitting work tile by tile instead of over the
union of sparse surfaces; render_layer admits its rect like render; hidden
layers no longer disable the proxy and uniform-area shortcuts; Blend If
groups nested deeper than two are judged by their result, so nesting costs
polynomial instead of exponential work; effect builds past an absolute byte
cap are skipped.

* CodeRabbit #8949: exact tile skips in filter_mask, allocated-tile scan in fit_stroke, contrasting backdrop in the nested-group test

- filter_mask mix/unmix: bare tiles (no tiles on either side) skip for
  non-alpha formats too when the two surfaces' default pixels are equal;
  differing defaults still get processed, so the clone's default pixel is
  never left wrong under a non-unit mask
- shape_split fit_stroke: scan the union of the three surfaces' allocated
  tiles (exact skip when all three defaults are transparent) instead of
  every tile of a 300k-canvas document; non-transparent defaults fall
  back to the full scan
- tests: the nested-groups assertion now uses a black backdrop so the
  asserted white can only come from rendering through the group chain

fixes CodeRabbit review comments (major/minor) on filter_mask.rs:27,29,
shape_split.rs:126, tests.rs:2354

* compose: skip a BTreeSet in fit_stroke — a sorted Vec compiles under the wasm toolchain (E0599 on ::drain there)
2026-10-23 15:33:01 -04:00
aiongg a75a414310 CI: cargo xtask ci is the gate, and the workflow runs it 2026-10-23 19:29:31 +00:00
Dylan M. Taylor ecd1a692a3 security(algo): bound working sets sized by caller-controlled extents (#8946)
* security(algo): bound working sets sized by caller-controlled extents

Zero-width inpaint grids, content-aware fill mosaics of turned thin images,
Liquify fields over huge canvases, tiny-scale reduction weights, warp tile
bookkeeping and per-tile source footprints, and windowed filters whose halo
follows an unclamped radius or a stacked Filter Gallery reach all asked for
memory sized by file or parameter input. Each is now bounded; halo
arithmetic saturates instead of overflowing.

* security(algo): budget variants by dimensions, size-check footprints first, widen the tile-halo maths

CodeRabbit follow-up:
- fill_cow settles the mosaic budget on variant dimensions only, so a
  variant's image and mask buffers are not built when the mosaic would
  exceed MAX_MOSAIC_PIXELS (complete falls back to the image itself).
- warp validates the footprint's pixel area against MAX_FOOTPRINT_PIXELS
  before src.has_tiles_in, so an oversized footprint returns without the
  tile-grid scan.
- auto_tile widens the input-derived halo arithmetic to i64 and clamps
  before the cast, so an i32::MAX radius cannot overflow in debug builds
  and the 2048 tile cap stands.

* fix(algo): drop the duplicate mosaic_size call left behind in fill_cow

The variant-budget rework kept both the new dimensions-based budget and
the old variants-based one; the old call no longer compiled after
mosaic_size started taking dimensions. Keep the comment that explains
the fallback.
2026-10-23 15:22:24 -04:00
Dylan M. Taylor a09c0ce85f test(gpu): match the planning error instead of err().expect() 2026-10-23 15:21:47 -04:00
Dylan M. Taylor 143c3977c2 Merge pull request #8959 from dylanmtaylor/security/cms-psd-raw-vector-parsers
security: bisect table/stop lookups; charge ICC curves; bound PSD/RAW buffers
2026-10-23 15:20:40 -04:00
Dylan M. Taylor 5b93901779 Merge pull request #8956 from dylanmtaylor/security/ipp-reply-deadline
security(ipp): total reply deadline, resumable chunk walk
2026-10-23 15:20:37 -04:00
Dylan M. Taylor 7d4c7f3889 Merge pull request #8953 from dylanmtaylor/security/raster-doc-sparse-tiles
security(raster,doc): tile counts, shared rebuilt tiles, slice merge index
2026-10-23 15:20:33 -04:00
Dylan M. Taylor a691aaf65b codecs: use u32 in the padded-truncated-JPEG test's bounds arithmetic (u64: From<i32> does not implement — E0277) 2026-10-23 15:08:50 -04:00
aiongg 437b012794 Merge pull request #8951 from aiongg/shared-gate
CI: the Linux gate runs through the suite's shared gate workflow
2026-10-23 15:08:49 -04:00
aiongg c3aa3f9e51 Tests: missing translations don't fail; xtask ci prints them
Delete the coverage tests, the per-language parity checks and the tests
of one language's exact wording. Catalog integrity, placeholder and
plural-form checks stay, as do the engine tests (locale resolution,
plural rules, fallback, language scoping, drawing in a language); those
compare against tr() or the plural rule rather than catalog wording.
Docs describe the report instead of a failing test.
2026-10-23 19:07:23 +00:00
aiongg cb297eeac1 xtask: i18n-coverage lists missing strings; ci prints them last
The report prints, per language, the source keys its catalog lacks (one
line for a language with none). `cargo xtask ci` runs it as its last step
and never fails on it: a missing translation shows in English. A report
that can't run prints a warning.
2026-10-23 19:07:23 +00:00
Dylan M. Taylor 75f5a9c126 packaging: use [[ for bash conditional tests (SonarCloud S7688) (#8914)
* packaging: use [[ for bash conditional tests (SonarCloud S7688)

SonarCloud flags every bare [ conditional in bash scripts under packaging/ as a reliability smell (rule S7688). Convert the flagged [ ... ] tests to [[ ... ]]: safer word-splitting and no glob surprises, same semantics for these string and file tests.

* packaging/web: parse size overrides as base 10 under [[
2026-10-23 15:03:12 -04:00
Dylan M. Taylor a8983a4060 security(codecs): budget truncated JPEG scans by scan data, document the animated WebP ICC charge
CodeRabbit follow-up:
- data_end counts the scan-data bytes it crosses, and decode's
  truncated-input bound is measured on those, not on bytes.len(): APP
  padding padded before the scan used to charge the budget without
  describing one more pixel.
- a regression test builds a truncated JPEG with ~256 KiB of complete
  COMMENT padding whose patched 20000x20000 frame was admissible under
  the file-length bound, and verifies padding alone cannot admit it
  (while the same file at its real size still recovers).
- Limits::max_alloc docs state the animated WebP charging, next to the
  PNG text/XMP sentence.
2026-10-23 14:44:28 -04:00
Dylan M. Taylor b20ccefffb security(gpu,ui-egui): bound clipped pass-through planning; sample pattern swatch pixels directly 2026-10-23 14:41:54 -04:00
Dylan M. Taylor 78ae50f7b2 security: bisect flat-table and gradient-stop lookups; charge ICC curve samples; bound PSD planes, RAW ljpeg retention and TIFF dump preview 2026-10-23 14:41:53 -04:00
Dylan M. Taylor 530e0b6b70 security(plugins): reject host routing keys, bound bands and start fuel, open without blocking on FIFOs 2026-10-23 14:41:52 -04:00
Dylan M. Taylor 93e605a2e9 security(ipp): total reply deadline; resumable chunk walk 2026-10-23 14:41:49 -04:00
Dylan M. Taylor 3729c3f664 security(raster,doc): count tile grids without walking them; share rebuilt tiles; index slice merges
Rect::tile_count counts a rect's tiles in u64; try_take_tiles uses it (no usize overflow on 32-bit). Surface::translated reuses one rebuilt tile for equal source-tile windows. auto_slices merges vertically adjacent runs through a hash index instead of searching the output.
2026-10-23 14:41:44 -04:00
Dylan M. Taylor 6da36b61f3 release: the git-sources gate moves into craft-common-actions (storytold/craft-common-actions#78) (#8952)
The check is shared at release.yml@main now; keep only the reusable call.
2026-10-23 14:41:09 -04:00
aiongg 9acf9a0cf9 CI: the Linux gate runs through the suite's shared gate workflow 2026-10-23 18:32:21 +00:00
Dylan M. Taylor b11ecc6ebf security(affinity): charge shared-object expansion against document-wide budgets (#8938)
Reject zero-width fixed-record arrays, borrow pixel state arrays instead of
collecting them per occurrence, charge FiEf slots, curve records and layer
name bytes across the document, bound mixed-text expansion before appending,
and cap distinct allocation-table ids (deletion records now hold no Entry).
2026-10-23 14:30:21 -04:00
Dylan M. Taylor c9892c8f8d security(codecs): refuse implausibly short truncated JPEG scans; charge WebP frame ICC copies
A truncated JPEG scan under a large declared frame was filled out by the
backend to the full admitted size; reject it when the file cannot plausibly
account for the pixels. Animated WebP frames each keep a copy of the ICC
profile, so the aggregate admission now counts it.
2026-10-23 14:12:04 -04:00
aiongg cf0960b520 Merge pull request #8915 from aiongg/ci-speed-2
CI: no debug info for dependencies, nextest in xtask ci, long sweeps spread over days
2026-10-23 13:48:36 -04:00
aiongg 9f0f7bc604 Merge pull request #8032 from aiongg/stored-path-resolve
Linked files: resolve stored paths with craft-docpath's resolve_absolute
2026-10-23 13:38:16 -04:00
aiongg 1f472d61ea Tests: report a bad PHOTOCRAFT_SWEEP_PART with assert!, which testkit's lints allow 2026-10-23 16:49:11 +00:00
aiongg 20ad9f1f4e Docs: the final check before a PR runs the full sweep 2026-10-23 16:40:24 +00:00
aiongg 066ad384cd Tests: refuse a PHOTOCRAFT_SWEEP_PART that isn't a part number 2026-10-23 16:40:24 +00:00
aiongg 7d9abd95af CI: the git-sources check parses .cargo/config and .cargo/config.toml
A source replacement, a patch or a path override in either cargo config never shows up in
Cargo.lock, so the check refuses them. Both files are parsed as TOML, as Cargo reads them.
2026-10-23 16:18:57 +00:00
Brandon ThomasandClaude Opus 5.5 e6d6fb45a4 Release 0.15.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:59:59 -04:00
Brandon ThomasandClaude Opus 5.5 ed1b6f4314 ci: run FreeBSD and Windows ARM64 checks on pushes to release
The release playbook runs the slow platform checks nightly and on every
push to release, so a regression shows up before a release is published.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:59:59 -04:00
Dylan M. TaylorandCodebuff f27656b910 fix: restrict droplet shim permissions and annotate test range (SonarCloud) (#8870)
The generated droplet shim only needs to run as its creator, so 0700 keeps
other local accounts from reading the CLI path it invokes. The reversed
range in the arrow-key test is the case under test, not an accident.

🤖 Generated with Codebuff

Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-23 09:57:10 -04:00
Dylan M. TaylorandCodebuff f346b5c8f4 fix(vector): bound hostile geometry and raster work (#8769)
* fix(vector): bound hostile geometry raster work

Guard geometry and tracing operations against malformed dimensions and degenerate inputs with bounded work and safe failures.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* fix(vector): address review (knot cap on split, relative identity tol, non-vacuous test)

* revert(geom): splitting past the quilt limit is intentional (smart_map test)

* fix(geom): cap identity tolerance at 1e-6 px

---------

Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-23 09:56:08 -04:00
92262d5950 fix(cms): confirm ICC profile identity by bytes, not the 64-bit hash alone (#8863)
Profile::content_hash is a fixed-key 64-bit SipHash of the ICC bytes, so a
crafted profile can share another profile's hash (about 2^32 work). Two
places took an equal hash as proof of an identical profile:

- transform::cached keyed its process-wide cache on the two hashes and the
  options, so a colliding profile was handed the other profile's cached
  transform and converted with the wrong colours.
- Profile::same_colors returned true on equal hashes, so a colliding
  profile was taken for the other one and a needed conversion was skipped.

Add Profile::same_bytes, which compares the ICC bytes (an Arc pointer check
first, then the hash, then the bytes). same_colors uses it instead of the
hash. Each transform cache entry now keeps the ICC bytes of its two
profiles; a hit counts only when they match, and a colliding pair gets its
own transform without replacing the cached entry. The transform is built
after the cache lock is released, as before.

The regression tests give Display P3 the content hash of sRGB (a stand-in
for a found collision): before the fix, same_colors called them the same
and the cache returned sRGB's transform for P3; now both see P3's colours.

Fixes #8613

Co-authored-by: John Turnbach <jturnbach@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:54:42 -04:00
aiongg ed1b9cff3f Merge pull request #8783 from wanikhawar/select-mask-edits
Select and Mask: tool edits as select.refineEdge params (engine, part 1 of 2)
2026-10-23 09:49:52 -04:00
Dylan M. TaylorandCodebuff 96042b8e7a fix(text): bound untrusted font and PSD text processing (#8768)
* fix(text): bound font paths and imported text processing

Reject encoded path tricks and cap resource-heavy font and PSD text processing to keep untrusted inputs bounded.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* fix(text): reject percent-encoded DEL in served paths; satisfy clippy chunks_exact lint

---------

Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-23 09:40:04 -04:00
Dylan M. TaylorandCodebuff 56d7009c78 fix(paint): validate gray tile dimensions safely (#8772)
* fix(paint): check tile dimensions before allocation math

Reject overflowing tile dimensions during deserialization and treat invalid in-memory tiles as empty safe previews and mipmaps.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* test(tile): assert the address-space overflow error on 32-bit targets

---------

Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-23 09:27:54 -04:00
Dylan M. TaylorandCodebuff ecff046ea1 fix(algo): avoid repeated copies of duplicate EXIF text (#8771)
* fix(algo): avoid copying duplicate EXIF text payloads

Keep the first valid text value for each EXIF tag, preventing duplicate entries from repeatedly decoding and copying large attacker-controlled strings.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* test(exif): count text decodes so the duplicate-tag test observes skipped payloads

---------

Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-23 09:27:48 -04:00
Dylan M. TaylorandCodebuff 1695f323e6 fix(psd): retain pattern budget charges after parse failures (#8767)
Keep allocation charges monotonic when malformed pattern blocks fail, so later sections cannot reuse budget already consumed.

🤖 Generated with Codebuff

Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-23 08:38:15 -04:00