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
6 changed files with 47 additions and 28 deletions
+1 -1
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")
+2 -7
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");
+2 -7
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");
+2 -6
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");
+2 -7
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");
+38
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