Skip to content

chore: release 0.26.0 #242

Description

@Goldziher

main is ready to ship as 0.26.0, but I cannot publish it: I have GitHub maintain on this repo, which does not carry crates.io ownership. The crate's owners are @RazrFalcon, @alerque, @LaurenzV and @khaledhosny.

@alerque — could you add me as a crates.io owner (or whichever existing owner is easiest to reach)? I'll follow up with my crates.io handle. That is the only thing standing between the current main and a release.

Also flagging this for visibility rather than landing a release unannounced: the backlog was large and some of it is behavioural.

What is on main

14 PRs merged, from 8 contributors, some open for over a year. Tests went 153 -> 196; the suite now runs in both debug and release.

Six of these are denial-of-service fixes against malformed input, with measured impact:

  • A 255-byte CFF table hung for over 30 seconds. STACK_LIMIT bounded subroutine nesting depth but not total invocations, so work grew as fanout^depth.
  • 8 bytes of GSUB caused a self-referential extension lookup to recurse unboundedly — a stack-overflow abort in debug, an infinite loop in release.
  • The same depth-vs-total-work mistake appeared independently in glyf/gvar composite outlining and in the COLRv1 paint graph.

The pattern is worth naming, because it recurred three times: a depth limit does not bound total work. With fan-out b and depth d, a small font forces b^d visits while never exceeding the cap. Each of these now bounds visits, not just depth.

One correctness bug is worth calling out separately: a well-formed 65535-glyph font was rejected outright, glyf was dropped, and every outline returned None (#226).

Breaking changes

Four, all listed under ### Changed in the changelog. The two that produce no compile error, and so need the most visibility:

  • Face::set_variation now returns None for an axis the face does not expose. It previously returned Some(()) unconditionally, contradicting its own documentation.
  • gvar-alloc now implies alloc rather than std, so default-features = false, features = ["gvar-alloc"] no longer satisfies the float guard and must select std or no-std-float explicitly.

Infrastructure

CI was structurally unable to see some failures. cargo test --release was red on main and had been for months — a #[should_panic] had enshrined a debug_assert!, which is compiled out in release. CI ran debug only. Likewise the c-api crate's Rust tests had never run in CI at all, because the repo root is not a workspace and a root cargo test never reaches it. Both now run, along with the alloc-without-std feature permutation, which no other leg covered.

MSRV is 1.88 and all four crates are on edition 2024. CONTRIBUTING.md did not exist and now does.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions