Skip to content

fix(deps): update dependencies - #26

Merged
tannevaled merged 1 commit into
mainfrom
renovate/deps
Aug 31, 2026
Merged

fix(deps): update dependencies#26
tannevaled merged 1 commit into
mainfrom
renovate/deps

Conversation

@tannevaled

@tannevaled tannevaled commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
github.com/go-gfx/gfx v0.18.0v0.19.0 age confidence
github.com/go-pdfkit/forms v0.2.2v0.3.0 age confidence
github.com/go-pdfkit/ops v0.8.0v0.11.0 age confidence
github.com/go-pdfkit/render v0.19.0v0.20.0 age confidence
github.com/go-widgets/toolkit v0.293.0v0.297.0 age confidence

Release Notes

go-gfx/gfx (github.com/go-gfx/gfx)

v0.19.0

Compare Source

go-pdfkit/forms (github.com/go-pdfkit/forms)

v0.3.0: — when the XML is the whole form

Compare Source

XFA came in two kinds and this package treated them as one.

Measured over 2 240 real government forms: 1 499 carry a form, 560 carry an XFA package, and 546 of those are static — a second, proprietary description of a form that is already there, on which everything here already works.

The other fourteen are dynamic: their pages hold a panel reading "Please wait… your PDF viewer may not be able to display this type of document", and the form is laid out from the XML by Adobe's reader and nothing else, the format having been removed from PDF 2.0. A caller meeting one has a document that looks blank and is not.

Form.Dynamic says which kind. Form.Packets hands back the parts of the package, so the values a form was filled with can be read — they live in the datasets part, as ordinary XML.

What measuring found. The library first answered "none dynamic" where the corpus said fourteen: Read refuses a form with no fields, and a dynamic XFA form usually has no AcroForm fields. The documents most needing to be reported were exactly the ones being refused. An empty field list with no XFA is still no form — 561 of 118 833 figure-corpus files carry one a producer left behind — but an empty one with a package is a form whose fields live elsewhere.

The library's count now matches the corpus exactly: 560 packages, 14 dynamic.

100% statement coverage, go vet and -race clean, nine cross-compile targets, CGO-free.

go-pdfkit/ops (github.com/go-pdfkit/ops)

v0.11.0: — print a page bigger than the paper

Compare Source

Doc.Poster(across, down) spreads each page over across×down sheets, so that the sheets printed and taped edge to edge make one page the size of a wall. It is the inverse of NUp.

Every sheet is the size of the page it came from, so a poster of an A4 document prints on A4 and each piece has the page's own proportions — pieces of some other shape do not tape back into the page they were cut from. Where the wall is not the page's shape, the page is enlarged as far as it will go inside it and centred.

The sheets meet exactly, with no overlap for taping, and that is argued rather than defaulted: an overlap would have to be a constant, because Poster is told how many sheets to use and not how wide the printer's unprinted border is. Meeting exactly is also the only arrangement that is exactly undone — every part of the page lands on one sheet and one only.

Judged by poppler, in CI. A page divided into a three-by-three grid, each cell a colour of its own with a black pip in its top-left corner, is postered and rendered: the colour says which cell a sheet shows, and the pip says which way up it is. A PDF's origin is at the bottom, so a poster can come out with every piece present and upside down — which no count of pages would catch. poppler is now installed in CI so that check runs there and not only on a machine that happens to have it.

100% statement coverage, go vet and -race clean, nine cross-compile targets, CGO-free.

v0.10.0: — the files a document carries

Compare Source

A PDF can hold whole files inside it — the spreadsheet a report was drawn from, the XML a form was filled from, the source of a figure. Every verb here dropped them.

The catalogue's /Names was dropped whole, on the ground that a name tree points into the document. True of /Dests, whose names point at pages this reorders and removes, and of /JavaScript, which is code. Not true of /EmbeddedFiles: a file inside a document belongs to no page, so nothing here can invalidate it — and nothing on the page says it is there, so nobody notices it went until the file is wanted. 45 of the 3 215 documents in the forms and scans corpora carry one.

Attachments lists what a document holds, Attach puts one in, Detach takes one out. A name already used is refused rather than quietly replacing what is there. A sanitised file still carries nothing inside it.

Files from several documents are all kept — two forms cannot be merged and two catalogues cannot be chosen between, but two sets of files can both be carried, because a file belongs to no page.

A specification pointing at no stream, or at bytes still in a filter nothing here unpacks, is not handed over as a file: passing those on gives somebody a spreadsheet that is not one.

Judged by poppler: pdfdetach lists one file before and two after a rotation and an addition, and saves both with the right bytes.

100% statement coverage, go vet and -race clean, nine cross-compile targets, CGO-free.

v0.9.0: — two piles into one, and a document on one sheet

Compare Source

Doc.Interleave takes pages from each document in turn. It is what a single-sided feeder leaves behind: a stack run through twice comes out as two files — the fronts and the backs — which is one document taken apart. Merging them end to end gives every front then every back; this gives the document. A shorter pile simply runs out, which is what a scanner leaves when the last sheet is single-sided.

Doc.OnePage stacks every page onto one sheet. A page is a unit of paper, not a unit of reading: a receipt, a chat log and a web page cut into A4 are one thing a printer divided. Narrower pages are centred.

The order is asserted rather than looked at: a PDF's origin is at the bottom, so the first page takes the largest offset. Reversed, every page is still there and the document is upside down.

And poppler was asked rather than ourselves — three marks at known heights come out at 28%, 48% and 70% of the stacked sheet, against 26.7%, 46.7% and 68.3% computed.

100% statement coverage, go vet and -race clean, nine cross-compile targets, CGO-free.

go-pdfkit/render (github.com/go-pdfkit/render)

v0.20.0: — a page cannot spend the machine

Compare Source

render.Images could be made to allocate without bound by an ordinary PDF. One document in a public test corpus drove it to 87 GB resident and climbing before it was killed.

The cause was not a missing ceiling. imagesIn walked a page's resources as a tree when they are a graph. In openpdf-core_src_test_resources_pdfsmartcopy_bec.pdf, the page names 37 form XObjects and each one names that same /Resources dictionary straight back: 37 dictionaries visited at depth one, 1 369 at two, 37⁸ at the depth limit — with each of the page's 40 pictures decoded again at every visit, four bytes a pixel. Depth three alone is 156 GB.

The repeated-decode behaviour seen on cerfa_10103.pdf was the same defect rather than a neighbour: those forms fan out by two, and 2⁰ + … + 2⁸ = 511. That page now returns 3 pictures, decoded once each.

Three changes

Each XObject is entered once, by reference. This removes the exponent, and also stops one picture reached through two different forms being handed back twice.

A picture is charged before it is made. Its declared /Width × /Height comes out of a budget before the decode, masks included. Past the limit it is refused with ErrTooMuchToDecode, naming the picture and the limit. A bound checked after the allocation would not have helped.

A codec is asked what it holds before it is handed the bytes. A hole in the above, found while building the fixture: a valid 8×8 JPEG of 376 bytes whose frame header is patched to 65 535 × 65 535 makes image/jpeg allocate 4 GB before it notices the scan data is missing — while its dictionary declares 64 pixels. Both codecs state their size from the header without allocating, so that is read first.

maxImagesPixels is 256 << 20 (1 GiB RGBA), chosen by measurement rather than by taste: across 10 659 corpus pages the largest names 31 814 093 pixels and the median 90 048, so no real page reaches a sixth of it.

Judged

Over the whole 2 268-document corpus: pages=10659 pictures=16220 refused=0 peakHeap=398MB, with the picture count identical before and after the codec guard. Every new test was re-run with its own fix removed and each one fails without it — including the lying-JPEG test, which asserts the decoder is never reached, since "nothing came back" was true before the fix too, once the 4 GB had been spent.

100% statement coverage under both Go 1.26.4 and 1.27.0, go vet and -race clean, nine cross-compile targets, CGO-free.

go-widgets/toolkit (github.com/go-widgets/toolkit)

v0.297.0

Compare Source

v0.296.0

Compare Source

v0.295.0

Compare Source

v0.294.0

Compare Source


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

@tannevaled
tannevaled merged commit 3f37b5a into main Aug 31, 2026
2 checks passed
@tannevaled
tannevaled deleted the renovate/deps branch August 31, 2026 11:46
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