Where: internal/imageprocessor/imageprocessor.go, resize, the FitCover case (also the default fit): img.Thumbnail(width, height, vips.InterestingCentre), on next at f743930. Found by the review of #278.
What is wrong: for fit=cover, libvips scales the source to cover the requested size and copies the whole uncropped result into memory before it crops the centre. For a thin source that result is far larger than the output. An 8192x64 source requested at 8192x8192 makes libvips ask for one block of about 24 GiB; 8192x1024 at 8192x8192 peaks at about 1.6 GB and takes 21 seconds. An 8192x1 source at 8192x8192 fails inside libvips ("output coordinates out of range") and answers 500. The same 8192x64 source with fit=fill takes 2.6 seconds and 25 MB. This also breaks the per-image memory figure README.md "Running under upaas" gives.
How it fails: anyone who can request an image from an allowlisted host, or holds a signed or encrypted URL that allows a large size, asks for a thin image at 8192x8192. One request can make pixa run out of memory and be killed.
Severity: high (a denial of service: AGENTS.md puts these at the top of TODO.md).
Plan: for fit=cover, cut the centre of the source to the requested size's proportions first, then resize that to the requested size, so no image larger than the source or the output is ever made. The output is the same centre crop as now.
Definition of done:
An 8192x64 and an 8192x1 source requested at 8192x8192 with fit=cover are served, each with a peak memory no larger than the output's and the source's decoded size together, measured and stated in the PR; no fit=cover request answers 500 for its shape.
fit=cover output keeps its size and centre crop for ordinary sources; no existing test changes.
Test first; make check green.
Package: internal/imageprocessor.
Model: opus-5-5
Where: `internal/imageprocessor/imageprocessor.go`, `resize`, the `FitCover` case (also the default fit): `img.Thumbnail(width, height, vips.InterestingCentre)`, on `next` at `f743930`. Found by the review of https://git.eeqj.de/sneak/pixa/pulls/278.
What is wrong: for `fit=cover`, libvips scales the source to cover the requested size and copies the whole uncropped result into memory before it crops the centre. For a thin source that result is far larger than the output. An 8192x64 source requested at 8192x8192 makes libvips ask for one block of about 24 GiB; 8192x1024 at 8192x8192 peaks at about 1.6 GB and takes 21 seconds. An 8192x1 source at 8192x8192 fails inside libvips ("output coordinates out of range") and answers 500. The same 8192x64 source with `fit=fill` takes 2.6 seconds and 25 MB. This also breaks the per-image memory figure `README.md` "Running under upaas" gives.
How it fails: anyone who can request an image from an allowlisted host, or holds a signed or encrypted URL that allows a large size, asks for a thin image at 8192x8192. One request can make pixa run out of memory and be killed.
Severity: high (a denial of service: `AGENTS.md` puts these at the top of `TODO.md`).
Plan: for `fit=cover`, cut the centre of the source to the requested size's proportions first, then resize that to the requested size, so no image larger than the source or the output is ever made. The output is the same centre crop as now.
Definition of done:
1. An 8192x64 and an 8192x1 source requested at 8192x8192 with `fit=cover` are served, each with a peak memory no larger than the output's and the source's decoded size together, measured and stated in the PR; no `fit=cover` request answers 500 for its shape.
2. `fit=cover` output keeps its size and centre crop for ordinary sources; no existing test changes.
3. Test first; `make check` green.
Package: `internal/imageprocessor`.
Model: opus-5-5
clawbot
self-assigned this 2026-10-15 23:24:11 +02:00
#284 cuts the centre of the source to the requested size's proportions before resizing for fit=cover; its body gives the measured peak memory. A computed side that rounds down to 0, found on the way, is #283.
Model: opus-5-5
https://git.eeqj.de/sneak/pixa/pulls/284 cuts the centre of the source to the requested size's proportions before resizing for `fit=cover`; its body gives the measured peak memory. A computed side that rounds down to 0, found on the way, is https://git.eeqj.de/sneak/pixa/issues/283.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Where:
internal/imageprocessor/imageprocessor.go,resize, theFitCovercase (also the default fit):img.Thumbnail(width, height, vips.InterestingCentre), onnextatf743930. Found by the review of #278.What is wrong: for
fit=cover, libvips scales the source to cover the requested size and copies the whole uncropped result into memory before it crops the centre. For a thin source that result is far larger than the output. An 8192x64 source requested at 8192x8192 makes libvips ask for one block of about 24 GiB; 8192x1024 at 8192x8192 peaks at about 1.6 GB and takes 21 seconds. An 8192x1 source at 8192x8192 fails inside libvips ("output coordinates out of range") and answers 500. The same 8192x64 source withfit=filltakes 2.6 seconds and 25 MB. This also breaks the per-image memory figureREADME.md"Running under upaas" gives.How it fails: anyone who can request an image from an allowlisted host, or holds a signed or encrypted URL that allows a large size, asks for a thin image at 8192x8192. One request can make pixa run out of memory and be killed.
Severity: high (a denial of service:
AGENTS.mdputs these at the top ofTODO.md).Plan: for
fit=cover, cut the centre of the source to the requested size's proportions first, then resize that to the requested size, so no image larger than the source or the output is ever made. The output is the same centre crop as now.Definition of done:
fit=coverare served, each with a peak memory no larger than the output's and the source's decoded size together, measured and stated in the PR; nofit=coverrequest answers 500 for its shape.fit=coveroutput keeps its size and centre crop for ordinary sources; no existing test changes.make checkgreen.Package:
internal/imageprocessor.Model: opus-5-5
#284 cuts the centre of the source to the requested size's proportions before resizing for
fit=cover; its body gives the measured peak memory. A computed side that rounds down to 0, found on the way, is #283.Model: opus-5-5