Skip to content

Fix release-build SIGSEGV in monotonic fill (stale right-horizontal link after vertical-run jump) - #11978

Open
gommzystudio wants to merge 1 commit into
bambulab:masterfrom
gommzystudio:fix/fill-rectilinear-monotonic-landing-link
Open

Fix release-build SIGSEGV in monotonic fill (stale right-horizontal link after vertical-run jump)#11978
gommzystudio wants to merge 1 commit into
bambulab:masterfrom
gommzystudio:fix/fill-rectilinear-monotonic-landing-link

Conversation

@gommzystudio

@gommzystudio gommzystudio commented Aug 21, 2026

Copy link
Copy Markdown

Summary

Fixes a random release-build SIGSEGV in the monotonic fill traversal that we hit in production via top-surface ironing (Layer::make_ironing()FillRectilinear). The same input would sometimes slice fine and sometimes crash, because the crash depends on which intersection carries the right-horizontal link.

Root cause

In both monotonic traversals in src/libslic3r/Fill/FillRectilinear.cpp (montonous_region_path_length and polylines_from_paths), iright accumulates the right-horizontal link while a vertical run is consumed:

  • going up: iright = std::max(iright, it->right_horizontal()); inside the do-loop
  • going down: if (int iright_new = it->right_horizontal(); iright_new != -1) iright = iright_new;

However, when the traversal follows a vertical_up() / vertical_down() link to continue on another run of the same vline (it = vline.intersections.data() + inext;), the landing intersection's right_horizontal() is never folded into iright.

If the only right link of the combined run lives at or after the landing point, iright remains -1 (or stale). The code afterwards does:

int inext = it->right_horizontal();
assert(iright != -1);
assert(inext == -1 || inext == iright);
const SegmentedIntersectionLine &vline_right = segs[i_vline + 1];
const SegmentIntersection *right = going_up ?
    &vertical_run_top(vline_right, vline_right.intersections[iright]) : ...

Both asserts are compiled out in release builds, so vline_right.intersections[iright] reads out of bounds with iright == -1 (crash), or traverses from a wrong intersection with a stale index (silent misbehavior).

Fix

Update iright at all four vertical-jump landing sites, using exactly the idiom the surrounding loops already use (max while going up, last non--1 while going down). Six added lines, no behavior change for paths that already computed a valid iright.

Validation

  • Two different models reproduced the crash reliably, each triggering it through a different ironed top surface (per-object ironing overrides enable the affected code path). One of them failed 11/11 consecutive CLI slices on Ubuntu (SIGSEGV, exit 139; reported as exit 127 through the AppImage wrapper).
  • With this patch applied to the unmodified v02.06.00.51 source, the same two models with unchanged zig-zag ironing passed 20/20 runs (10 per model), plus another 20/20 with the packaged AppImage.
  • Output parity: identical ironing section counts per model before/after (107 and 5), identical estimated print times across repeats, full structural and spatial G-code validation (no missing regions).
  • A core dump of the unpatched build shows the crash inside FillRectilinear during Layer::make_ironing().

The affected file is byte-identical between v02.06.00.51 and current master, so the bug is still present on master.

Notes

…ink after vertical-run jumps

In both monotonic traversals (montonous_region_path_length and
polylines_from_paths), iright tracks the right-horizontal link while a
vertical run is consumed. When the traversal follows a vertical_up()/
vertical_down() link to another run on the same vline, the landing
intersection's right_horizontal() was never folded into iright.

If the only right link of the combined run lives at or after the landing
point, iright stays -1 (or stale). The subsequent
vline_right.intersections[iright] access is only guarded by an assert,
which is compiled out in release builds, so release builds read out of
bounds and crash with SIGSEGV (observed via Layer::make_ironing on
real models), or silently traverse from a wrong intersection.

Update iright at all four landing sites using the same idiom the
surrounding loops already use (max while going up, last non -1 while
going down). Paths that previously computed a valid iright are
unaffected.
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