From 12720ccbd8a0a4570f43e336e1d133136c4da6c6 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 18 Jul 2026 01:45:54 +0800 Subject: [PATCH] Gate network plugin loading to ABI-compatible series Trim the version whitelist to the latest series plus the pinned legacy build, and reject out-of-series configured versions at startup, compatibility check, and load failure - falling back to the latest installed build or the clean re-download flow so the config never keeps pointing at an unsupported build. --- src/slic3r/GUI/GUI_App.cpp | 36 +++++++++++++++++++++ src/slic3r/Utils/bambu_networking.hpp | 26 +++++++++++++-- tests/slic3rutils/test_network_versions.cpp | 34 ++++++++++++++----- 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index bccb9f073e..7b8d811349 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1967,6 +1967,13 @@ bool GUI_App::check_networking_version() BOOST_LOG_TRIVIAL(info) << "check_networking_version: network_ver=" << network_ver << ", expected=" << studio_ver; + // A configured version outside the whitelisted series must never pass as compatible, + // even if it matches the loaded library - its ABI does not match this build. + if (!use_legacy_network_plugin() && !is_supported_network_version(studio_ver)) { + m_networking_compatible = false; + return false; + } + if (network_ver.length() >= 8 && studio_ver.length() >= 8) { if (network_ver.substr(0,8) == studio_ver.substr(0,8)) { m_networking_compatible = true; @@ -3451,6 +3458,21 @@ bool GUI_App::on_init_network(bool try_backup) std::string config_version = app_config->get_network_plugin_version(); if (should_load_networking_plugin) { + // A version outside the whitelisted series (e.g. 02.03.00.62 configured by an older + // Orca release) must not be loaded - its ABI no longer matches this build. Fall back + // to the latest supported build if it is already on disk; otherwise clear the + // configured version so the normal empty-version download flow takes over (the + // download URL and install adoption both derive from the configured version, so it + // must not keep pointing at the unsupported build). + if (!config_version.empty() && !is_supported_network_version(config_version)) { + std::string latest = get_latest_network_version(); + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": configured plugin version " << config_version + << " is no longer supported, falling back to " << latest; + config_version = BBLNetworkPlugin::versioned_library_exists(latest) ? latest : ""; + app_config->set_network_plugin_version(config_version); + app_config->save(); + } + if (config_version.empty()) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": no version configured, need to download"; m_networking_need_update = true; @@ -3505,6 +3527,20 @@ bool GUI_App::on_init_network(bool try_backup) } } else { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll failed"; + // A failed install can leave the config naming a build that never made it to + // disk (download_plugin() adopts the downloaded version up front so that + // install_plugin() can name the library after it). If the whitelisted latest + // is still installed, fall back to it instead of dropping the user into the + // re-download flow without networking. + std::string latest = get_latest_network_version(); + if (config_version != latest && BBLNetworkPlugin::versioned_library_exists(latest)) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": falling back to installed " << latest; + config_version = latest; + app_config->set_network_plugin_version(latest); + app_config->save(); + load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(false, config_version); + goto __retry; + } if (should_load_networking_plugin) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, need upload network module"; m_networking_need_update = true; diff --git a/src/slic3r/Utils/bambu_networking.hpp b/src/slic3r/Utils/bambu_networking.hpp index a7d40f171f..9145769e8d 100644 --- a/src/slic3r/Utils/bambu_networking.hpp +++ b/src/slic3r/Utils/bambu_networking.hpp @@ -359,11 +359,12 @@ struct NetworkLibraryVersion { const char* warning; }; +// Only the latest series and the legacy build are offered/loadable: the host binds the +// modern ABI (by-value struct layouts, function signatures) of exactly one series, plus +// a dedicated shim for the legacy build. Older 02.0x series expect different layouts +// and must not be loaded - see is_supported_network_version(). static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = { {"02.08.01.52", "02.08.01.52", nullptr, true, nullptr}, - {"02.03.00.62", "02.03.00.62", nullptr, false, nullptr}, - {"02.01.01.52", "02.01.01.52", nullptr, false, nullptr}, - {"02.00.02.50", "02.00.02.50", nullptr, false, "This version may crash on startup due to Bambu Lab's signature verification."}, {BAMBU_NETWORK_AGENT_VERSION_LEGACY, BAMBU_NETWORK_AGENT_VERSION_LEGACY " (legacy)", nullptr, false, nullptr}, }; @@ -377,6 +378,25 @@ inline const char* get_latest_network_version() { return AVAILABLE_NETWORK_VERSIONS[0].version; } +// True when the version can be loaded through the ABI this build was compiled against: +// an exact whitelist entry, or a build from the same AA.BB.CC series as a non-legacy +// whitelist entry (the plugin ABI is stable within a series, and the OTA sync only ever +// installs same-series updates). Anything else - in particular older 02.0x series a +// previous Orca release whitelisted - expects different by-value struct layouts and +// function signatures and must not be loaded. +inline bool is_supported_network_version(const std::string& version) { + for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) { + const std::string base = AVAILABLE_NETWORK_VERSIONS[i].version; + if (version == base) + return true; + if (base == BAMBU_NETWORK_AGENT_VERSION_LEGACY) + continue; + if (version.size() >= 8 && base.size() >= 8 && version.compare(0, 8, base, 0, 8) == 0) + return true; + } + return false; +} + struct NetworkLibraryVersionInfo { std::string version; std::string base_version; diff --git a/tests/slic3rutils/test_network_versions.cpp b/tests/slic3rutils/test_network_versions.cpp index 781214cba3..f35041a469 100644 --- a/tests/slic3rutils/test_network_versions.cpp +++ b/tests/slic3rutils/test_network_versions.cpp @@ -66,14 +66,14 @@ TEST_CASE_METHOD(PluginFolderFixture, "Same-series OTA plugin versions are surfa add_plugin("02.08.01.55"); // same series as the whitelisted latest -> listed add_plugin("02.09.00.10"); // unknown series -> not listed add_plugin("02.08.01.52-custom"); // suffixed build of a whitelisted base -> listed (existing behavior) - add_plugin("02.03.00.62"); // exactly a whitelisted version -> no duplicate + add_plugin("02.03.00.62"); // series no longer whitelisted -> not listed auto versions = get_all_available_versions(); REQUIRE(count_version(versions, "02.08.01.55") == 1); REQUIRE(count_version(versions, "02.09.00.10") == 0); REQUIRE(count_version(versions, "02.08.01.52-custom") == 1); - REQUIRE(count_version(versions, "02.03.00.62") == 1); + REQUIRE(count_version(versions, "02.03.00.62") == 0); size_t latest_pos = versions.size(), ota_pos = versions.size(); for (size_t i = 0; i < versions.size(); ++i) { @@ -98,16 +98,34 @@ TEST_CASE_METHOD(PluginFolderFixture, "Same-series OTA plugin versions are surfa REQUIRE_FALSE(versions[latest_pos].is_latest); REQUIRE_FALSE(versions[latest_pos].is_installed); - // A whitelisted version whose library exists on disk is marked installed. - for (const auto& info : versions) { - if (info.version == "02.03.00.62") - REQUIRE(info.is_installed); - } - // The static default used for download and update-check decisions is unchanged. REQUIRE(std::string(get_latest_network_version()) == "02.08.01.52"); } +TEST_CASE("Only whitelisted series pass the load gate", "[NetworkVersions]") +{ + // Exact whitelist entries. + REQUIRE(is_supported_network_version("02.08.01.52")); + REQUIRE(is_supported_network_version(BAMBU_NETWORK_AGENT_VERSION_LEGACY)); + + // Same-series OTA builds and suffixed dev builds of the whitelisted latest. + REQUIRE(is_supported_network_version("02.08.01.55")); + REQUIRE(is_supported_network_version("02.08.01.52-custom")); + + // Series whitelisted by previous Orca releases - their ABI no longer matches. + REQUIRE_FALSE(is_supported_network_version("02.03.00.62")); + REQUIRE_FALSE(is_supported_network_version("02.01.01.52")); + REQUIRE_FALSE(is_supported_network_version("02.00.02.50")); + + // Unknown series, legacy siblings, and malformed values. + REQUIRE_FALSE(is_supported_network_version("02.09.00.10")); + std::string legacy = BAMBU_NETWORK_AGENT_VERSION_LEGACY; + std::string legacy_sibling = legacy.substr(0, 9) + (legacy.substr(9) == "99" ? "98" : "99"); + REQUIRE_FALSE(is_supported_network_version(legacy_sibling)); + REQUIRE_FALSE(is_supported_network_version("")); + REQUIRE_FALSE(is_supported_network_version("02.08")); +} + TEST_CASE_METHOD(PluginFolderFixture, "Legacy series never adopts discovered builds", "[NetworkVersions]") { // A different build of the legacy series must not be surfaced: is_legacy_version()