diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0b62fd0d6f..8238f5be85 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6215,7 +6215,8 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill static constexpr const char* support_transition_label = "support transition"; static constexpr const char* support_ironing_label = "support ironing"; - static const auto speed_for_path = [&](double length, ExtrusionRole role, double default_speed = -1.0) { + // Not static: it captures `this` by reference. + const auto speed_for_path = [&](double length, ExtrusionRole role, double default_speed = -1.0) { if (!is_support(role) || length > SMALL_PERIMETER_LENGTH(NOZZLE_CONFIG(small_support_perimeter_threshold))) return default_speed; diff --git a/tests/fff_print/test_support_material.cpp b/tests/fff_print/test_support_material.cpp index 24c0e9cdc5..f854939c8c 100644 --- a/tests/fff_print/test_support_material.cpp +++ b/tests/fff_print/test_support_material.cpp @@ -93,3 +93,14 @@ SCENARIO("Support layer Z honors contact distance", "[SupportMaterial]") } } } + +// extrude_support once held a `static` lambda capturing `this`, so a second export in the +// same process dereferenced a returned stack frame (ASan: stack-use-after-return). +TEST_CASE("Support G-code emission survives a second slice in the same process", "[SupportMaterial][Regression]") +{ + const std::string first = slice({ TestMesh::overhang }, { { "enable_support", 1 } }); + REQUIRE(! layers_with_role(first, "support").empty()); + + const std::string second = slice({ TestMesh::overhang }, { { "enable_support", 1 } }); + REQUIRE(! layers_with_role(second, "support").empty()); +}