Fix crash when MinGW toolchains are detected on macOS

The "RealGcc" toolchain factory does all the autodetection, and happily
autodetects toolchains of various type, also MinGW toolchains on macOS
if installed e.g. via Homebrew. But, the MinGW toolchain factory is not
added on macOS. So we end up with toolchains that have a typeId that is
not supported by any toolchain factory, which leads to various asserts,
and finally to a crash.

The patch filters out any "GCC related" toolchains that actually do not
have a factory, during the autodetection in the "RealGCC" toolchain
factory. It also adds some QTC_ASSERTs, though these are in the end not
able to prevent crashes elsewhere (e.g. when opening the settings
dialog).

Fixes: QTCREATORBUG-32127
Change-Id: If5c17d1a3aff9df4ec4172c9ed7901990ac7f3ce
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Eike Ziller
2025-02-13 15:51:57 +01:00
parent b9b55a6d0e
commit 1d7bc22710
3 changed files with 13 additions and 3 deletions

View File

@@ -1555,7 +1555,14 @@ Toolchains GccToolchainFactory::autoDetect(const ToolchainDetector &detector) co
detector.alreadyKnown, detector.alreadyKnown,
GccToolchain::RealGcc /*sic!*/); GccToolchain::RealGcc /*sic!*/);
return result; // Filter out toolchains with a type that we actually do not have a factory for
// e.g. when finding a MinGW toolchain on macOS
const auto [filteredResult, toDelete] = Utils::partition(result, [](Toolchain *tc) {
return factoryForType(tc->typeId()) != nullptr;
});
qDeleteAll(toDelete);
return filteredResult;
} }
Toolchains GccToolchainFactory::detectForImport(const ToolchainDescription &tcd) const Toolchains GccToolchainFactory::detectForImport(const ToolchainDescription &tcd) const

View File

@@ -211,6 +211,7 @@ bool Toolchain::canShareBundle(const Toolchain &other) const
{ {
QTC_ASSERT(typeId() == other.typeId(), return false); QTC_ASSERT(typeId() == other.typeId(), return false);
QTC_ASSERT(language() != other.language(), return false); QTC_ASSERT(language() != other.language(), return false);
QTC_ASSERT(factory(), return false);
if (int(factory()->supportedLanguages().size()) == 1) if (int(factory()->supportedLanguages().size()) == 1)
return false; return false;
@@ -711,7 +712,7 @@ Toolchain *ToolchainFactory::restore(const Store &data)
QTC_ASSERT(tc, return nullptr); QTC_ASSERT(tc, return nullptr);
tc->fromMap(data); tc->fromMap(data);
if (!tc->hasError()) if (!tc->hasError() && QTC_GUARD(tc->typeId() == supportedToolchainType()))
return tc; return tc;
delete tc; delete tc;
@@ -921,6 +922,7 @@ ToolchainBundle::ToolchainBundle(const Toolchains &toolchains, HandleMissing han
{ {
// Check pre-conditions. // Check pre-conditions.
QTC_ASSERT(!m_toolchains.isEmpty(), return); QTC_ASSERT(!m_toolchains.isEmpty(), return);
QTC_ASSERT(factory(), return);
QTC_ASSERT(m_toolchains.size() <= factory()->supportedLanguages().size(), return); QTC_ASSERT(m_toolchains.size() <= factory()->supportedLanguages().size(), return);
for (const Toolchain * const tc : toolchains) { for (const Toolchain * const tc : toolchains) {
QTC_ASSERT(factory()->supportedLanguages().contains(tc->language()), return); QTC_ASSERT(factory()->supportedLanguages().contains(tc->language()), return);

View File

@@ -244,7 +244,8 @@ static void setToolchainsFromAbis(Kit *k, const LanguagesAndAbis &abisByLanguage
for (auto it = abisByCategory.cbegin(); it != abisByCategory.cend(); ++it) { for (auto it = abisByCategory.cbegin(); it != abisByCategory.cend(); ++it) {
const QList<ToolchainBundle> matchingBundles const QList<ToolchainBundle> matchingBundles
= Utils::filtered(bundles, [&it](const ToolchainBundle &b) { = Utils::filtered(bundles, [&it](const ToolchainBundle &b) {
return b.factory()->languageCategory() == it.key() && b.targetAbi() == it.value(); return b.factory() && b.factory()->languageCategory() == it.key()
&& b.targetAbi() == it.value();
}); });
if (matchingBundles.isEmpty()) { if (matchingBundles.isEmpty()) {