Fix issue #105: linear_extrude scale= heap corruption on non-finite values - #107
Conversation
…alues
CsgEvaluator::evalExtrusion() special-cases "scale" to support both a
scalar and a 2-vector, but unlike every other extrusion param (which
routes through evalNumber(), folding non-finite doubles to 0.0) and
unlike "angle" (which explicitly resolves non-finite to a fallback),
the scale branch assigned sv.asNumber() straight into scale_x/scale_y.
1/0, -1/0, and 0/0 are real IEEE-754 Numbers per the interpreter's
arithmetic propagation, so they sailed through the isNumber() check
unclamped. MeshEvaluator/Manifold::Extrude then lerped every extruded
vertex toward that inf/nan scale, corrupting the heap ("free(): invalid
next size (fast)") — reproduced with linear_extrude(scale=1/0), matching
OpenSCAD's own linear_extrude-parameter-tests.scad corpus file.
Now a non-finite scalar or vector component is rejected, leaving
scale_x/scale_y unset so MeshEvaluator falls back to its default 1.0
(no scaling) — the same "malformed scale is ignored" behavior already
used for a stray 3-element vector.
particlesector
left a comment
There was a problem hiding this comment.
Reviewed. Fix is correct and narrowly scoped: scale= now goes through the same std::isfinite() guard already used for angle= (<cmath> was already included), and leaving scale_x/scale_y unset correctly falls back to MeshEvaluator's default of 1.0 (verified at src/csg/MeshEvaluator.cpp:426-427). Test case covers 1/0, -1/0, 0/0, the 2-vector form, and a finite-value regression check.
One nit: scale=[1/0, 2] is tested, but not the symmetric scale=[2, 1/0] (non-finite in the second component only) — probably not worth a separate case given the shared guard, just flagging.
No blocking issues.
Generated by Claude Code
Generated by Claude Code
Mirrors the existing scale=[1/0, 2] case to also cover a non-finite value in the vector's second component only.
|
Good catch — added the symmetric Generated by Claude Code |
particlesector
left a comment
There was a problem hiding this comment.
Symmetric scale=[2, 1/0] case added, addressing the earlier nit. Fix logic unchanged and still correct. LGTM.
Generated by Claude Code
Generated by Claude Code
Summary
Fixes #105 —
linear_extrude-parameter-tests.scadcrashed with heap corruption (free(): invalid next size (fast)).Root cause:
CsgEvaluator::evalExtrusion()special-casesscale=to accept either a scalar or a 2-vector. Every other extrusion param (height,twist,slices,convexity, ...) routes throughInterpreter::evalNumber(), which folds non-finite doubles (1/0,-1/0,0/0) down to0.0.angle=(forrotate_extrude) gets its own explicitstd::isfinite()fallback. But thescale=branch assignedsv.asNumber()straight intoscale_x/scale_ywith no such guard — and1/0/-1/0/0/0are real IEEE-754Numbervalues per the interpreter's arithmetic propagation, so they sailed right past theisNumber()type check unclamped.Those non-finite values then flowed into
MeshEvaluator::evalExtrusion()→manifold::Manifold::Extrude(..., {scaleX, scaleY}), which lerps every extruded vertex toward the given scale across the profile's height — with an inf/nan scale, this corrupts the heap.Fix: reject non-finite scale values (scalar or per-component in the 2-vector form), leaving
scale_x/scale_yunset soMeshEvaluatorfalls back to its existing default of1.0(no scaling) — the same "malformed scale is ignored" behavior already used for e.g. a stray 3-element scale vector.Verification
chiselcad_cliagainst the pre-fix code and ran alinear_extrude(scale=1/0) square(10);file —free(): invalid next size (fast)/Aborted (core dumped), matching the issue.undef,1/0,-1/0,0/0,"",true,[1:3],3) fed throughscale=.CsgEval:linear_extrude non-finite scale is rejected, not passed throughtotests/test_csg_evaluator.cpp, verifying the resolved IR params (the half of the pipeline that's unit-testable without linking Manifold — see the file's existing header comment on this)../chiselcad_tests→ all 3699 assertions in 665 test cases pass.Test plan
./chiselcad_tests(full suite) passes1/0,-1/0,0/0) and non-finite 2-vector componentchiselcad_clion both pre-fix and post-fix buildsGenerated by Claude Code