Skip to content

fix(geometry): resolve transform lengths per axis and per font-size - #286

Merged
LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/geometry-transform-lengths
Sep 22, 2026
Merged

LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/geometry-transform-lengths

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Audit finding carried by this chantier. Refs #220 (RM-15).

`apply_transform_chain` resolves `translate`/`translateX`/`translateY` lengths through this context. The paint pass resolves the very same functions through `LengthContext { ..., parent_size: box_layout.width.max(height), font_size: node.css.font_size_px_or(16.0), ... }` and then splits it into per-axis `length_ctx_x`/`length_ctx_y` (crates/rustmotion-core/src/engine/paint_pass.rs:229-250, used at :953-962). Two divergences: (a) `em` — a `font-size: 96px` text with `transform: "translateX(-10em)"` is moved -960px by the renderer but only -160px by the validator, so a component at x=200 that renders at x=-760 (fully off-frame) validates clean; (b) percentage translate — the validator uses `max(w, h)` on both axes, the exact mistake paint_pass.rs:236-242 calls out in a comment ("never max(width, height) on both axes"), which over-estimates on the short axis and produces false positives. Note the `--strict-anim` path funnels animated transforms through this same function (geometry.rs:1482), so it inherits both errors.

Refs #220
@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 22, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 22, 2026
@LeadcodeDev
LeadcodeDev merged commit 4886960 into chantier/audit-2026-09 Sep 22, 2026
0 of 3 checks passed
LeadcodeDev added a commit that referenced this pull request Sep 22, 2026
…286)

`apply_transform_chain` resolves `translate`/`translateX`/`translateY` lengths through this context. The paint pass resolves the very same functions through `LengthContext { ..., parent_size: box_layout.width.max(height), font_size: node.css.font_size_px_or(16.0), ... }` and then splits it into per-axis `length_ctx_x`/`length_ctx_y` (crates/rustmotion-core/src/engine/paint_pass.rs:229-250, used at :953-962). Two divergences: (a) `em` — a `font-size: 96px` text with `transform: "translateX(-10em)"` is moved -960px by the renderer but only -160px by the validator, so a component at x=200 that renders at x=-760 (fully off-frame) validates clean; (b) percentage translate — the validator uses `max(w, h)` on both axes, the exact mistake paint_pass.rs:236-242 calls out in a comment ("never max(width, height) on both axes"), which over-estimates on the short axis and produces false positives. Note the `--strict-anim` path funnels animated transforms through this same function (geometry.rs:1482), so it inherits both errors.

Refs #220
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant