From 84ab7afd444f37e122e250ac4ca2e922472c42f2 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 21 Jan 2024 22:54:54 +0300 Subject: [PATCH] Make BA2 extension hash calculation safer (#7784) --- components/bsa/ba2dx10file.cpp | 2 +- components/bsa/ba2file.cpp | 8 ++++++++ components/bsa/ba2file.hpp | 1 + components/bsa/ba2gnrlfile.cpp | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/components/bsa/ba2dx10file.cpp b/components/bsa/ba2dx10file.cpp index 593ca64949..aa3f8d0581 100644 --- a/components/bsa/ba2dx10file.cpp +++ b/components/bsa/ba2dx10file.cpp @@ -177,7 +177,7 @@ namespace Bsa return std::nullopt; // folder not found uint32_t fileHash = generateHash(fileName); - uint32_t extHash = *reinterpret_cast(ext.data() + 1); + uint32_t extHash = generateExtensionHash(ext); auto iter = it->second.find({ fileHash, extHash }); if (iter == it->second.end()) return std::nullopt; // file not found diff --git a/components/bsa/ba2file.cpp b/components/bsa/ba2file.cpp index b4fc7f9ec2..17cfb03866 100644 --- a/components/bsa/ba2file.cpp +++ b/components/bsa/ba2file.cpp @@ -46,4 +46,12 @@ namespace Bsa return result; } + uint32_t generateExtensionHash(std::string_view extension) + { + uint32_t result = 0; + for (size_t i = 0; i < 4 && i < extension.size() - 1; i++) + result |= static_cast(extension[i + 1]) << (8 * i); + return result; + } + } // namespace Bsa diff --git a/components/bsa/ba2file.hpp b/components/bsa/ba2file.hpp index e5a68d3caa..75a2ce8d61 100644 --- a/components/bsa/ba2file.hpp +++ b/components/bsa/ba2file.hpp @@ -7,6 +7,7 @@ namespace Bsa { uint32_t generateHash(const std::string& name); + uint32_t generateExtensionHash(std::string_view extension); } #endif diff --git a/components/bsa/ba2gnrlfile.cpp b/components/bsa/ba2gnrlfile.cpp index f3961a3bc4..02df12593c 100644 --- a/components/bsa/ba2gnrlfile.cpp +++ b/components/bsa/ba2gnrlfile.cpp @@ -172,7 +172,7 @@ namespace Bsa return FileRecord(); // folder not found, return default which has offset of sInvalidOffset uint32_t fileHash = generateHash(fileName); - uint32_t extHash = *reinterpret_cast(ext.data() + 1); + uint32_t extHash = generateExtensionHash(ext); auto iter = it->second.find({ fileHash, extHash }); if (iter == it->second.end()) return FileRecord(); // file not found, return default which has offset of sInvalidOffset