From a7cd9ff36d2385ca0b26dc8a097e69d4ef791ced Mon Sep 17 00:00:00 2001 From: Maschell Date: Wed, 11 Feb 2026 11:44:52 +0100 Subject: [PATCH] Fix crash when loading incompatible plugins --- source/PluginManagement.cpp | 2 +- source/utils/StringTools.cpp | 33 +++++++++++++++++++++++++++++++++ source/utils/StringTools.h | 18 ++---------------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/source/PluginManagement.cpp b/source/PluginManagement.cpp index 6702a25..e0689be 100644 --- a/source/PluginManagement.cpp +++ b/source/PluginManagement.cpp @@ -48,7 +48,7 @@ PluginManagement::loadPlugins(const std::vector &pluginDataLi plugins.emplace_back(std::move(*metaInfo), PluginLinkInformation::CreateStub(), pluginDataWrapper.getPluginData()); } } else { - auto errMsg = string_format("Failed to load plugin: %s", *pluginDataWrapper.getPluginData()->getSource().c_str()); + auto errMsg = string_format("Failed to load plugin: %s", pluginDataWrapper.getPluginData()->getSource().c_str()); if (error == PLUGIN_PARSE_ERROR_INCOMPATIBLE_VERSION) { errMsg += ". Incompatible version."; } diff --git a/source/utils/StringTools.cpp b/source/utils/StringTools.cpp index 021b256..ea79ecf 100644 --- a/source/utils/StringTools.cpp +++ b/source/utils/StringTools.cpp @@ -28,8 +28,41 @@ #include +#include + +#include +#include #include +std::string string_format(const char *format, ...) { + char stack_buf[128]; + va_list args; + va_start(args, format); + int len = std::vsnprintf(stack_buf, sizeof(stack_buf), format, args); + va_end(args); + + if (len >= 0 && static_cast(len) < sizeof(stack_buf)) { + return std::string(stack_buf, len); + } + + // on error return the unformatted string + if (len < 0) { + return std::string(format); + } + + const auto buf = make_unique_nothrow(static_cast(len)); + if (!buf) { + DEBUG_FUNCTION_LINE_ERR("string_format failed, not enough memory"); + OSFatal("WiiUPluginBackend: string_format failed, not enough memory"); + return std::string(""); + } + + va_start(args, format); + std::vsnprintf(buf.get(), len, format, args); + va_end(args); + return std::string(buf.get(), len); +} + std::string StringTools::truncate(const std::string &str, const size_t width, const bool show_ellipsis) { if (str.length() > width - 3) { if (show_ellipsis) { diff --git a/source/utils/StringTools.h b/source/utils/StringTools.h index 013ad31..dec5ad2 100644 --- a/source/utils/StringTools.h +++ b/source/utils/StringTools.h @@ -28,24 +28,10 @@ #include "logger.h" #include "utils.h" -#include - -#include #include -template -std::string string_format(const std::string_view format, Args... args) { - const int size_s = std::snprintf(nullptr, 0, format.data(), args...) + 1; // Extra space for '\0' - const auto size = static_cast(size_s); - const auto buf = make_unique_nothrow(size); - if (!buf) { - DEBUG_FUNCTION_LINE_ERR("string_format failed, not enough memory"); - OSFatal("string_format failed, not enough memory"); - return std::string(""); - } - std::snprintf(buf.get(), size, format.data(), args...); - return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside -} +std::string string_format(const char *format, ...) + WUT_FORMAT_PRINTF(1, 2); class StringTools { public: