From CodeRabbit's review of #2607: when the blocks before the first image descriptor could not
be walked, check_fillable fell back to treating the whole file as pixel data and the whole
screen as covered, so padding could let a large canvas through the bound. A GIF with no first
frame has nothing to decode, so it is now Malformed ("no readable first frame").
The image crate's GIF decoder also stops at such files when it opens them, so this was not
reachable through read_header or decode in the cases tried; the bound no longer relies on the two
walks agreeing. Unit test a_gif_with_no_readable_first_frame_is_refused calls check_fillable on a
GIF whose comment runs to the end of the file; the old fallback returned Ok for its 400 MP screen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtjHGt5gnCHXgLt4NbGorf
From echelon's review of #2607:
- A GIF's LZW data now bounds its first frame's own width x height, not the logical screen's,
so a valid GIF with a small first frame on a larger screen imports.
- A canvas the file's data leaves mostly blank (a GIF screen larger than its first frame, or an
RLE BMP larger than its runs could cover at 255 pixels per 2 bytes) still costs its whole size
in from_decoder, so it is limited to 4 MP (SPARSE_MAX_PIXELS) and refused before the decoder
allocates it. Densely coded canvases keep the max_pixels limit.
Tests: a 64-byte RLE BMP declaring 2001 x 2000 or 32000 x 32000 is refused ("mostly blank");
the RLE BMP that ends early still opens at 2000 x 2000; a GIF with a 1 x 1 first frame opens on
a 2000 x 2000 screen and is refused on a 32767 x 32767 one. The first three fail without this
change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtjHGt5gnCHXgLt4NbGorf
A message a catalog lacks, or translates as an empty string, shows in
English and fails nothing:
- build.rs no longer requires every formats catalog to carry the same
messages, and tr_format! gets a last arm that formats the English
source, so a message no catalog has builds.
- Coverage tests (every language translates X) and tests of one
language's exact wording are gone; the language-switching, layout,
date, placeholder and user-value tests read the catalog's own value
instead of a hard-coded translation.
- i18n::tests::translation_gaps_report lists, per language, the plain
and format messages it lacks and its untranslated What's New lines.
It always passes; cargo xtask ci
runs it from the test step's binary after the tests.
- catalogs_load checks that every catalog file is a JSON object of
strings with each key once; it.json named "Dimensions" twice.
doc_path::resolve uses craft_docpath::resolve_absolute; a path that resolves but is not absolute here is reported as not on this computer. Adds tests for Windows-form, GVFS-relative and colon-in-name paths, and a git-sources check in nix.yml and release.yml.
Found while testing crates/catalog/src/rules.rs:673 (num_op), reached via Rule::matches at :956-957
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
dialog_field took the focus back every frame while the field wasn't being edited, so Tab never
reached the check box, Cancel or OK of New Album, New Smart Album, Save Metadata Preset and the
other one-field dialogs. It now takes the focus once, when the dialog opens (the way the keyword
dialogs already did).
* CI: run the gate through craft-common-actions' shared gate.yml; FreeBSD nightly and on release
ci.yml is new: it calls the shared workflow (cached apt packages, nextest, main-only cache saves, Cargo.lock check). FreeBSD and Windows ARM64 run nightly and on pushes to release instead of on pull requests. Depends on storytold/craft-common-actions#69.
* CI: the gate installs no nextest (xtask ci runs cargo test)
- ORF_DECODED's Camedia branch drops the redundant \\S+ before .*; with two anchored greedies the scanner can no longer retry the same substring count-for-count at lower and lower split points (same match set, verified on 14 body strings).
- {c: 0 for c in classes} is now dict.fromkeys(classes, 0), which the rule wants and which stones the per-class counters.
* CI: dev profile keeps line tables for workspace crates and no debug info for dependencies
* Control server tests: persistent_requests_and_slow_replies_outlive_the_idle_read_timeout no longer races the idle timeout
Each request (and the closing half-shutdown) reaches the socket before the
worker reads, so on a slow machine only the reply waits outlast the 100 ms
idle timeout, as the test intends. The idle test sends its input the same
way, and the no-frames test allows 5 s instead of 2 s to give up.
* CI: one integration-test binary per crate
Each crate's tests/*.rs become modules of tests/it/main.rs (51 test files
into 13 binaries, plus 6 that stay their own). Inner #![cfg] attributes
move to the mod lines. Files that change state for the whole process keep
a binary of their own: codecs jxl_tail_heap and raw sr2_heap (dhat global
allocator), gpu shutdown, shutdown_first and memory, ui-egui shutdown.
Docs, comments and the GPU probe name the new paths and targets
(--test it <module>::); the CI report names an it binary's skips after
the crate.
* CI: tests under nextest, doctests apart, one wasm check
xtask ci runs the tests with cargo nextest run --lib --bins --tests when
cargo-nextest is installed, else cargo test with the same targets and a
one-line notice; doctests run after them with cargo test --workspace --doc.
The heif and hardware GPU steps use the same runner. Examples stay out of
the test build (clippy --all-targets still checks them). Concurrent tests
under nextest follow the RUST_TEST_THREADS cap (NEXTEST_TEST_THREADS).
The wasm check is one cargo check --keep-going over the same crates, and
clippy runs with --keep-going.
* CI: tests run under cargo test by default, nextest with LIGHTCRAFT_NEXTEST=1 (per-process scene cache)
* Packaging: pin the Windows signing client and check its hash
* Packaging: pin appimagetool and check its hash
* Packaging: no pinned tool or runtime for an architecture exits clearly; pin the AppImage runtime and pass it with --runtime-file
Bash scripts use [[ ]] for tests, functions name their positional
parameters and end with an explicit return, and the app-specific packaging
check writes its ::error:: annotations to stderr. No behaviour change.
Dropping a wgpu buffer after the device's thread-locals are gone can
abort; the device owns the memory either way.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
The command sweep ran metadata.downloadPlaceNames with empty params, which
starts a real download from download.geonames.org into the settings folder.
The sweep now skips it (the command has its own loopback-server tests) and
asserts that no place names download was started.
Co-Authored-By: Claude <noreply@anthropic.com>
`median_row` (the running median under process V2's highlights/shadows base) kept a sorted
window of f32 and, per pixel, found the leaving and entering values with two binary searches
on `total_cmp`, then `remove` + `insert`. The searches mispredicted on most steps.
Now the window holds `i32` keys that order exactly like `f32::total_cmp` (the same transform
it applies), both ranks come from one branch-free counting pass the compiler vectorizes, and
one `copy_within` moves the keys between them. Equal keys are equal bits, so the output is
unchanged bit for bit.
24 MP Sony A7 III log luminance, one P-core, interleaved: r = 9 (export) 1977-2027 ms ->
912-958 ms, r = 3 1249-1292 -> 658-724, r = 24 2180-2261 -> 972-1030. All cores, r = 9:
170-188 -> 86-102 ms. The GPU path has its own median and is untouched.
New test: special values (NaN of both signs, signed zeros, infinities), long ties and planes
narrower than the window match a per-pixel sorted median bit for bit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0121DZuByhKyGLHw5C9JkUue