mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 13:32:44 +00:00
fix: guard per-filament array reads against short config arrays (#14789)
* fix: guard H2C per-filament array reads against short config arrays The H2C tool-ordering, wipe-tower, and g-code export paths index per-filament config arrays by filament/tool id. A config with fewer entries than the filament count (partial or legacy projects, minimal test configs) makes these reads run past the end of the vector: silent under a normal STL, but UB that aborts under the flatpak build's bounds-checked STL (_GLIBCXX_ASSERTIONS). Route the reads through the existing clamping accessors (get_at, get_filament_category, is_in_same_extruder) and add a small clamp helper for filament_change_length. The guards are no-ops when the arrays are sized to the filament count, so correctly specified configs are unaffected. * fix: size the grouping context's filament_info to the filament count build_filament_group_context built model_info.filament_info by walking filament_type, so a config whose filament_type is shorter than the filament count produced a short vector. FilamentGroup indexes filament_info by filament id, so clamping the individual reads only moved the out-of-bounds access downstream. Loop to filament_nums and read all three fields through get_at, and drop filament_ids entries past the filament count, since the grouping code pairs filament_ids and filament_info by position. Adds a regression test with four filaments and one-entry filament_type / filament_is_support. Without the fix it throws bad_alloc from copying a garbage std::string read past the end. * fix: guard the carousel nozzle-change length reads too The carousel branch added in b90ac13d86/b0dddb4648 reads m_filaments_change_length by tool id without a bounds check, the same pattern this branch already routed through filament_change_length_at a few lines above in both plan_toolchange and plan_tower_new. * fix: guard WipeTower per-filament array reads against short config arrays The BambuStudio WipeTower sync reintroduced raw per-filament array indexing that reads out of bounds when a config leaves an array shorter than the filament count: m_physical_extruder_map in format_line_M104/M109 (indexed even when empty), and m_filament_categories in get_wall_skip_points and get_wall_filament_for_all_layer. Silent on a normal STL, a hard abort under the bounds-checked STL the Flatpak build uses. Bounds-check the physical extruder map before indexing (omitting the T token, as the existing -1 path already does), and route the two raw m_filament_categories reads through the clamping get_filament_category() accessor the surrounding code already uses. No change for correctly-sized configs.
This commit is contained in:
@@ -163,6 +163,50 @@ TEST_CASE("H2C multi-nozzle: filaments get distinct nozzles on the 6-nozzle extr
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Grouping context spans the filament count with mis-sized config arrays", "[ToolOrdering][H2C]")
|
||||
{
|
||||
// FilamentGroup indexes the grouping context's filament_info by filament id, so a short
|
||||
// per-filament array must not shorten it: the reads run off the end.
|
||||
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||
// Single 6-nozzle extruder: opens the grouping engine without needing a BBL multi-extruder.
|
||||
config.option<ConfigOptionFloats>("nozzle_diameter", true)->values = {0.4};
|
||||
config.option<ConfigOptionIntsNullable>("extruder_max_nozzle_count", true)->values = {6};
|
||||
config.option<ConfigOptionStrings>("extruder_nozzle_stats", true)->values = {"Standard#6"};
|
||||
|
||||
// Four filaments, with filament_type / filament_is_support left short on purpose.
|
||||
config.option<ConfigOptionStrings>("filament_colour", true)->values = {"#FF0000", "#00FF00", "#0000FF", "#FFFF00"};
|
||||
config.option<ConfigOptionStrings>("filament_type", true)->values = {"PLA"};
|
||||
config.option<ConfigOptionBools>("filament_is_support", true)->values = {0};
|
||||
config.option<ConfigOptionFloats>("filament_diameter", true)->values = {1.75, 1.75, 1.75, 1.75};
|
||||
config.option<ConfigOptionInts>("filament_map", true)->values = {1, 1, 1, 1};
|
||||
config.option<ConfigOptionFloats>("flush_volumes_matrix", true)->values = std::vector<double>(16, 140.);
|
||||
config.option<ConfigOptionFloats>("flush_multiplier", true)->values = {1.};
|
||||
|
||||
Model model;
|
||||
model.add_object("cube", "", make_cube(20, 20, 20))->add_instance();
|
||||
|
||||
Print print;
|
||||
print.apply(model, config);
|
||||
// apply() does not pad the per-filament arrays, so the mis-sizing survives into the engine.
|
||||
REQUIRE(print.config().filament_type.values.size() < print.config().filament_colour.values.size());
|
||||
|
||||
std::vector<std::vector<unsigned int>> layer_filaments = {{0, 1}, {1, 2}, {2, 3}};
|
||||
|
||||
SECTION("short per-filament arrays still yield one entry per filament") {
|
||||
auto result = ToolOrdering::get_recommended_filament_maps(layer_filaments, &print, FilamentMapMode::fmmAutoForFlush, {}, {});
|
||||
REQUIRE(result.get_extruder_map(false).size() == 4);
|
||||
for (int f = 0; f < 4; ++f)
|
||||
REQUIRE(result.get_extruder_id(f) == 0);
|
||||
}
|
||||
|
||||
SECTION("filament_ids longer than the filament count is truncated, not paired past the end") {
|
||||
config.option<ConfigOptionStrings>("filament_ids", true)->values = {"a", "b", "c", "d", "e", "f"};
|
||||
print.apply(model, config);
|
||||
auto result = ToolOrdering::get_recommended_filament_maps(layer_filaments, &print, FilamentMapMode::fmmAutoForFlush, {}, {});
|
||||
REQUIRE(result.get_extruder_map(false).size() == 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("H2C dynamic selector: per-layer nozzle ids reach the g-code surface", "[ToolOrdering][H2C][Dynamic]")
|
||||
{
|
||||
// The per-layer regroup engine
|
||||
|
||||
Reference in New Issue
Block a user