From 47de49064735412d4712b00fedd6db13ede53da1 Mon Sep 17 00:00:00 2001 From: Clifford Garwood Date: Fri, 2 Oct 2026 08:13:38 -0400 Subject: [PATCH] Size the IMEX test fixtures' flush matrix per nozzle The IMEX fixtures set seven nozzles but kept multifilament_config's single filaments x filaments flush block. get_flush_volumes_matrix splits that block across the nozzles, leaving each with 7 values, and ToolOrdering::reorder_extruders_for_minimum_flush_volume then reads them as a 7 x 7 matrix, past the end of the buffer. One of the affected tests segfaulted on Windows x64; ASan reproduces the overflow in that test on Linux, where it passed only by luck. The fixtures now repeat the block once per nozzle, as the GUI does, and size flush_multiplier to match, since append_full_config takes the nozzle count from it. The helper is shared in test_helpers. Co-authored-by: HanifKoh <76276251+HanifKoh@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 --- tests/fff_print/test_helpers.cpp | 13 +++++++++++++ tests/fff_print/test_helpers.hpp | 4 ++++ tests/fff_print/test_imex_mode_gcode.cpp | 1 + tests/fff_print/test_imex_slice_offset.cpp | 1 + tests/fff_print/test_multifilament.cpp | 1 + 5 files changed, 20 insertions(+) diff --git a/tests/fff_print/test_helpers.cpp b/tests/fff_print/test_helpers.cpp index 89f9f9fdd1..585132bc6e 100644 --- a/tests/fff_print/test_helpers.cpp +++ b/tests/fff_print/test_helpers.cpp @@ -224,6 +224,19 @@ DynamicPrintConfig multifilament_config(unsigned int filaments, std::initializer return config; } +void size_flush_to_nozzles(DynamicPrintConfig &config) +{ + // One filaments x filaments flush block and one flush multiplier per nozzle, as the GUI + // sizes them when the nozzle count changes; a single block leaves each nozzle's slice short. + const size_t nozzles = config.option("nozzle_diameter")->values.size(); + auto &flush = config.option("flush_volumes_matrix", true)->values; + const std::vector block = flush; + for (size_t i = 1; i < nozzles; ++i) + flush.insert(flush.end(), block.begin(), block.end()); + for (const char *key : { "flush_multiplier", "flush_multiplier_fast" }) + config.option(key, true)->resize(nozzles); +} + void init_print(std::vector &&meshes, Slic3r::Print &print, Slic3r::Model &model, const DynamicPrintConfig &config_in, const std::vector> *per_object_overrides, bool arrange, size_t instances) { diff --git a/tests/fff_print/test_helpers.hpp b/tests/fff_print/test_helpers.hpp index cbdc90c3d9..1dee775092 100644 --- a/tests/fff_print/test_helpers.hpp +++ b/tests/fff_print/test_helpers.hpp @@ -72,6 +72,10 @@ Slic3r::Model model(const std::string& model_name, TriangleMesh&& _mesh); DynamicPrintConfig multifilament_config(unsigned int filaments, std::initializer_list extra = {}); +// Repeat multifilament_config's single flush block, and the flush multipliers, once per nozzle. +// Call after setting nozzle_diameter to more than one nozzle. +void size_flush_to_nozzles(DynamicPrintConfig &config); + // Apply `meshes` and config to `print`/`model`, each object with `instances` copies; optional per-object overrides, // auto-arranged unless `arrange` is false. void init_print(std::vector &&meshes, Slic3r::Print &print, Slic3r::Model &model, const DynamicPrintConfig &config_in, diff --git a/tests/fff_print/test_imex_mode_gcode.cpp b/tests/fff_print/test_imex_mode_gcode.cpp index 04643864e7..d9772a1ea6 100644 --- a/tests/fff_print/test_imex_mode_gcode.cpp +++ b/tests/fff_print/test_imex_mode_gcode.cpp @@ -114,6 +114,7 @@ static void imex_7x4_printer(DynamicPrintConfig &config) // compares the two scripts and nothing else. { "gcode_flavor", "klipper" }, }); + size_flush_to_nozzles(config); } // Set the mode scripts positionally, one per name in imex_mode_names. Assigning the vector diff --git a/tests/fff_print/test_imex_slice_offset.cpp b/tests/fff_print/test_imex_slice_offset.cpp index c12c0f20cb..03477dff7d 100644 --- a/tests/fff_print/test_imex_slice_offset.cpp +++ b/tests/fff_print/test_imex_slice_offset.cpp @@ -173,6 +173,7 @@ static void imex_printer(DynamicPrintConfig &config) { "initial_layer_print_height","0.2" }, { "gcode_flavor", "klipper" }, }); + size_flush_to_nozzles(config); } // Route every region to one filament. An unset *_filament_id is not "inherit": diff --git a/tests/fff_print/test_multifilament.cpp b/tests/fff_print/test_multifilament.cpp index 9f4f34dcc9..fc24268b0a 100644 --- a/tests/fff_print/test_multifilament.cpp +++ b/tests/fff_print/test_multifilament.cpp @@ -741,6 +741,7 @@ static void imex_7x4_printer(DynamicPrintConfig &config) // "G10 S P" from the same code, so the flavor is pinned rather than defaulted. { "gcode_flavor", "klipper" }, }); + size_flush_to_nozzles(config); } // Route every region to one filament. An unset *_filament_id is not "inherit":