fix(view): circle shape SIGABRT + CircleTo stack overflow#46
Merged
Conversation
Circle node shape (LP_SHAPE_TYPE == CIRCLE) crashed in two places in CDasherViewSquare, both exercised via the C-API render path that was never tested with the legacy circle layout. Bug 1 (SIGABRT): IsSpaceAroundNode() asserted CoversCrosshair() for any node spanning the visible region. That invariant only holds for rectangular shapes — a circle/ellipse (or triangle/quadric) can span the full visible height yet legitimately miss the crosshair. Guard the assert to DISJOINT/OVERLAPPING_RECTANGLE and CUBE. Bug 2 (SIGSEGV / stack overflow): CircleTo() subdivided the arc recursively with no depth bound. Degenerate endpoints (DasherSpaceArc can pass y with |cy - y| > r => sqrt(negative) => NaN, or integer-rounding stall once y1,y3 are within 1) defeated the convergence test and recursed until the stack was exhausted. Add a depth cap (kMaxCircleSubdivisionDepth = 20), a no-progress guard (y1 >= y3), and clamp the sqrt argument to >= 0. Tests: test_circle_geometry.cpp (C-API smoke) and test_circle_view_internal.cpp (deterministic internal test that crashes on unpatched code via UBSan NaN cast + ASan SEGV, passes clean after). Signed-off-by: will wade <willwade@gmail.com>
This was referenced Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes two crashes in
CDasherViewSquaretriggered whenLP_SHAPE_TYPE == CIRCLE(the legacy circular/compass node shape), both reachable via the C-API render path that was never tested with it.Bug 1 —
IsSpaceAroundNodeSIGABRT (debug builds)DasherViewSquare.cpp:527assertedCoversCrosshair(...)for any node spanning the visible region. That invariant only holds for rectangular shapes — a circle/ellipse (and triangles/quadrics) can span the full visible height yet legitimately miss the crosshair, so the assert was unsound.Fix: guard the assert to
DISJOINT_RECTANGLE,OVERLAPPING_RECTANGLE, andCUBE; non-rectangular shapes fall through to their correct per-shape computation.Bug 2 —
CircleTostack overflow (SIGSEGV)CircleTo()(DasherViewSquare.cpp:441) subdivided the arc recursively with no depth bound. The convergence test could be defeated two ways:DasherSpaceArc(the game-mode brachistochrone, GameModule.cpp:239) can pass arc endpoints with|y - cy| > r, makingsq(r) - sq(cy-y2)negative →sqrt(negative)→ NaN → UB on themyintcast. UBSan: "nan is outside the range of representable values of type 'long long'".y1, y3are within 1, the midpoint stops advancing.Either way the recursion never terminated → stack exhaustion → SIGSEGV.
Fix:
kMaxCircleSubdivisionDepth = 20— 2^20 segments is far more than any real arc needs; ~13 levels reaches pixel accuracy),y1 >= y3no-progress guard,sqrtargument to>= 0.The remaining arc at the cap is approximated by a straight line, which is visually fine at that granularity.
Audit for similar issues
Per the bug report's heads-up ("we may have other settings like this"), I checked every
DASHER_ASSERTand recursive draw function in the file:DasherLine2Screen(only other recursive draw fn) — bounded by integer-coordinate halving (~log₂(MAX_Y) ≈ 22 levels) + convergence guards. Safe.TruncateTri's asserts are internal to the triangle clipper; hold for triangle geometry. In scope only for triangle shapes.LP_SHAPE_TYPEdispatch sites (NewRender,CoversCrosshair,IsSpaceAroundNode) already handleCIRCLE.So
CircleTowas the sole unbounded recursion andIsSpaceAroundNode's was the sole geometry-unsound assert.Tests
test_circle_geometry.cpp— C-API smoke (circle frames render, deep forward driving, parameter switching in/out of circle mode).test_circle_view_internal.cpp— deterministic internal test drivingDasherSpaceArc/CircleTowith degenerate coords (both LeftToRight and TopToBottom). Verified it crashes on the unpatched code (UBSan NaN cast + ASan SEGV) and passes clean after the fix.Verification
deterministic_testspass