From 89a6172acf2fa7efdb78a87b8efb8c8d95b591b3 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Mon, 28 Sep 2026 22:34:37 +0200 Subject: [PATCH] fix: refuse to load x64 zones in x86 --- .../Game/IW4/ZoneLoaderFactoryIW4.cpp | 14 +++- .../Game/IW5/ZoneLoaderFactoryIW5.cpp | 71 ++++++++++++------- 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp index aeefec81..34f8f7a8 100644 --- a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp @@ -195,6 +195,18 @@ namespace return std::nullopt; } + bool CanLoadZone(const ZoneLoaderInspectionResultIW4& inspectionResult) + { +#ifdef ARCH_x86 + if (GameVariant::GetVariantById(inspectionResult.m_generic_result.m_variant_id)->GetWordSize() == GameWordSize::ARCH_64) + { + con::warn("x64 zones are only supported by a x64 OAT build!"); + return false; + } +#endif + return true; + } + void SetupBlock(ZoneMemory& zoneMemory) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) @@ -301,7 +313,7 @@ namespace std::optional ZoneLoaderFactory::InspectZoneHeader(ZoneDataPeeking& filePeek) const { auto resultIw4 = InspectZoneHeaderIw4(filePeek); - if (!resultIw4) + if (!resultIw4 || !CanLoadZone(*resultIw4)) return std::nullopt; return resultIw4->m_generic_result; diff --git a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp index fb20effa..1218f487 100644 --- a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp +++ b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp @@ -91,6 +91,49 @@ namespace return GameVariantId::IW5_PC32; } + std::optional InspectZoneHeaderIw5(ZoneDataPeeking& filePeek) + { + const auto& header = filePeek.PeekStruct(); + if (header.m_version != ZoneConstants::ZONE_VERSION) + return std::nullopt; + + if (!memcmp(header.m_magic, ZoneConstants::MAGIC_SIGNED_INFINITY_WARD, std::char_traits::length(ZoneConstants::MAGIC_SIGNED_INFINITY_WARD))) + { + return ZoneLoaderInspectionResult{ + .m_game_id = GameId::IW5, + .m_variant_id = DeterminePcVariant(filePeek, true), + .m_is_official = true, + .m_is_signed = true, + .m_is_encrypted = false, + }; + } + + if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, std::char_traits::length(ZoneConstants::MAGIC_UNSIGNED))) + { + return ZoneLoaderInspectionResult{ + .m_game_id = GameId::IW5, + .m_variant_id = DeterminePcVariant(filePeek, false), + .m_is_official = false, + .m_is_signed = false, + .m_is_encrypted = false, + }; + } + + return std::nullopt; + } + + bool CanLoadZone(const ZoneLoaderInspectionResult& inspectionResult) + { +#ifdef ARCH_x86 + if (GameVariant::GetVariantById(inspectionResult.m_variant_id)->GetWordSize() == GameWordSize::ARCH_64) + { + con::warn("x64 zones are only supported by a x64 OAT build!"); + return false; + } +#endif + return true; + } + void SetupBlock(ZoneMemory& zoneMemory) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) @@ -182,33 +225,11 @@ namespace std::optional ZoneLoaderFactory::InspectZoneHeader(ZoneDataPeeking& filePeek) const { - const auto& header = filePeek.PeekStruct(); - if (header.m_version != ZoneConstants::ZONE_VERSION) + const auto result = InspectZoneHeaderIw5(filePeek); + if (!result || !CanLoadZone(*result)) return std::nullopt; - if (!memcmp(header.m_magic, ZoneConstants::MAGIC_SIGNED_INFINITY_WARD, std::char_traits::length(ZoneConstants::MAGIC_SIGNED_INFINITY_WARD))) - { - return ZoneLoaderInspectionResult{ - .m_game_id = GameId::IW5, - .m_variant_id = DeterminePcVariant(filePeek, true), - .m_is_official = true, - .m_is_signed = true, - .m_is_encrypted = false, - }; - } - - if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, std::char_traits::length(ZoneConstants::MAGIC_UNSIGNED))) - { - return ZoneLoaderInspectionResult{ - .m_game_id = GameId::IW5, - .m_variant_id = DeterminePcVariant(filePeek, false), - .m_is_official = false, - .m_is_signed = false, - .m_is_encrypted = false, - }; - } - - return std::nullopt; + return result; } std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneDataPeeking& filePeek,