1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-10-14 06:56:33 +00:00

Handle errors when computing stream size for BSA

This commit is contained in:
elsid 2025-09-19 19:26:22 +02:00
parent 796202f435
commit 801224749f
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
6 changed files with 47 additions and 28 deletions

View file

@ -321,7 +321,7 @@ ENDIF()
add_component_dir (files
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager
constrainedfilestream memorystream hash configfileparser openfile constrainedfilestreambuf conversion
istreamptr streamwithbuffer
istreamptr streamwithbuffer utils
)
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")

View file

@ -12,6 +12,7 @@
#include <components/esm/fourcc.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/files/conversion.hpp>
#include <components/files/utils.hpp>
#include <components/misc/strings/lower.hpp>
#include "ba2file.hpp"
@ -80,13 +81,7 @@ namespace Bsa
std::ifstream input(mFilepath, std::ios_base::binary);
// Total archive size
std::streamoff fsize = 0;
if (input.seekg(0, std::ios_base::end))
{
fsize = input.tellg();
input.seekg(0);
}
const std::streamsize fsize = Files::getStreamSizeLeft(input);
if (fsize < 24) // header is 24 bytes
fail("File too small to be a valid BSA archive");

View file

@ -11,6 +11,7 @@
#include <components/esm/fourcc.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/files/conversion.hpp>
#include <components/files/utils.hpp>
#include <components/misc/strings/lower.hpp>
#include "ba2file.hpp"
@ -75,13 +76,7 @@ namespace Bsa
std::ifstream input(mFilepath, std::ios_base::binary);
// Total archive size
std::streamoff fsize = 0;
if (input.seekg(0, std::ios_base::end))
{
fsize = input.tellg();
input.seekg(0);
}
const std::streamsize fsize = Files::getStreamSizeLeft(input);
if (fsize < 24) // header is 24 bytes
fail("File too small to be a valid BSA archive");

View file

@ -31,6 +31,7 @@
#include <components/esm/fourcc.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/files/utils.hpp>
using namespace Bsa;
@ -106,12 +107,7 @@ void BSAFile::readHeader()
std::ifstream input(mFilepath, std::ios_base::binary);
// Total archive size
std::streamoff fsize = 0;
if (input.seekg(0, std::ios_base::end))
{
fsize = input.tellg();
input.seekg(0);
}
const std::streamsize fsize = Files::getStreamSizeLeft(input);
if (fsize < 12)
fail("File too small to be a valid BSA archive");

View file

@ -37,6 +37,7 @@
#include <components/files/constrainedfilestream.hpp>
#include <components/files/conversion.hpp>
#include <components/files/utils.hpp>
#include <components/misc/strings/lower.hpp>
#include "memorystream.hpp"
@ -50,13 +51,7 @@ namespace Bsa
std::ifstream input(mFilepath, std::ios_base::binary);
// Total archive size
std::streamoff fsize = 0;
if (input.seekg(0, std::ios_base::end))
{
fsize = input.tellg();
input.seekg(0);
}
const std::streamsize fsize = Files::getStreamSizeLeft(input);
if (fsize < 36) // Header is 36 bytes
fail("File too small to be a valid BSA archive");

View file

@ -0,0 +1,38 @@
#ifndef COMPONENTS_FILES_UTILS_H
#define COMPONENTS_FILES_UTILS_H
#include <cerrno>
#include <format>
#include <istream>
#include <stdexcept>
#include <system_error>
namespace Files
{
inline std::streamsize getStreamSizeLeft(std::istream& stream)
{
const auto begin = stream.tellg();
if (stream.fail())
throw std::runtime_error(
std::format("Failed to get current file position: {}", std::generic_category().message(errno)));
stream.seekg(0, std::ios_base::end);
if (stream.fail())
throw std::runtime_error(
std::format("Failed to seek end file position: {}", std::generic_category().message(errno)));
const auto end = stream.tellg();
if (stream.fail())
throw std::runtime_error(
std::format("Failed to get current file position: {}", std::generic_category().message(errno)));
stream.seekg(begin);
if (stream.fail())
throw std::runtime_error(
std::format("Failed to seek original file position: {}", std::generic_category().message(errno)));
return end - begin;
}
}
#endif