1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-12-25 18:03:08 +00:00

Use fail function to verify nif stream state

If there is a failure to read the file like incomplete read, bad returns
false, but fail returns true. This is important for reading number of
items more than the file actually has.
This commit is contained in:
elsid 2025-09-19 13:51:31 +02:00
parent b49b048f72
commit 1ae0aadfed
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
4 changed files with 37 additions and 18 deletions

View file

@ -1,5 +1,13 @@
#include "stream.hpp"
#include <osg/Vec2f>
#include <osg/Vec3f>
#include <osg/Vec4f>
#include <format>
#include <stdexcept>
#include <string>
namespace Bgsm
{
template <>
@ -30,8 +38,9 @@ namespace Bgsm
throw std::runtime_error("Requested string length is too large: " + std::to_string(length));
str = std::string(length, '\0');
mStream->read(str.data(), length);
if (mStream->bad())
throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars");
if (mStream->fail())
throw std::runtime_error(std::format(
"Failed to read sized string of {} chars: {}", length, std::generic_category().message(errno)));
std::size_t end = str.find('\0');
if (end != std::string::npos)
str.erase(end);

View file

@ -3,7 +3,7 @@
#include <array>
#include <cassert>
#include <cstdint>
#include <format>
#include <istream>
#include <stdexcept>
#include <string>
@ -23,9 +23,9 @@ namespace Bgsm
{
static_assert(std::is_arithmetic_v<T>, "Buffer element type is not arithmetic");
pIStream->read(reinterpret_cast<char*>(dest), numInstances * sizeof(T));
if (pIStream->bad())
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") buffer of "
+ std::to_string(numInstances) + " instances");
if (pIStream->fail())
throw std::runtime_error(std::format("Failed to read typed ({}) buffer of {} instances: {}",
typeid(T).name(), numInstances, std::generic_category().message(errno)));
if constexpr (Misc::IS_BIG_ENDIAN)
for (std::size_t i = 0; i < numInstances; i++)
Misc::swapEndiannessInplace(dest[i]);

View file

@ -1,6 +1,10 @@
#include "nifstream.hpp"
#include <cerrno>
#include <format>
#include <span>
#include <stdexcept>
#include <system_error>
#include <components/toutf8/toutf8.hpp>
@ -55,8 +59,9 @@ namespace Nif
{
std::string str(length, '\0');
mStream->read(str.data(), length);
if (mStream->bad())
throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars");
if (mStream->fail())
throw std::runtime_error(std::format(
"Failed to read sized string of {} chars: {}", length, std::generic_category().message(errno)));
size_t end = str.find('\0');
if (end != std::string::npos)
str.erase(end);
@ -76,8 +81,9 @@ namespace Nif
{
std::string result;
std::getline(*mStream, result);
if (mStream->bad())
throw std::runtime_error("Failed to read version string");
if (mStream->fail())
throw std::runtime_error(
std::format("Failed to read version string: {}", std::generic_category().message(errno)));
return result;
}
@ -86,8 +92,9 @@ namespace Nif
size_t size = get<uint32_t>();
std::string str(size, '\0');
mStream->read(str.data(), size);
if (mStream->bad())
throw std::runtime_error("Failed to read string palette of " + std::to_string(size) + " chars");
if (mStream->fail())
throw std::runtime_error(std::format(
"Failed to read string palette of {} chars: {}", size, std::generic_category().message(errno)));
return str;
}

View file

@ -5,10 +5,13 @@
#include <array>
#include <cassert>
#include <cerrno>
#include <format>
#include <istream>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <system_error>
#include <type_traits>
#include <vector>
@ -40,9 +43,9 @@ namespace Nif
std::is_arithmetic_v<T> || std::is_same_v<T, Misc::float16_t>, "Buffer element type is not arithmetic");
static_assert(!std::is_same_v<T, bool>, "Buffer element type is boolean");
pIStream->read((char*)dest, numInstances * sizeof(T));
if (pIStream->bad())
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") buffer of "
+ std::to_string(numInstances) + " instances");
if (pIStream->fail())
throw std::runtime_error(std::format("Failed to read typed ({}) dynamic buffer of {} instances: {}",
typeid(T).name(), numInstances, std::generic_category().message(errno)));
if constexpr (Misc::IS_BIG_ENDIAN)
for (std::size_t i = 0; i < numInstances; i++)
Misc::swapEndiannessInplace(dest[i]);
@ -61,9 +64,9 @@ namespace Nif
std::is_arithmetic_v<T> || std::is_same_v<T, Misc::float16_t>, "Buffer element type is not arithmetic");
static_assert(!std::is_same_v<T, bool>, "Buffer element type is boolean");
pIStream->read((char*)dest, numInstances * sizeof(T));
if (pIStream->bad())
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") dynamic buffer of "
+ std::to_string(numInstances) + " instances");
if (pIStream->fail())
throw std::runtime_error(std::format("Failed to read typed ({}) dynamic buffer of {} instances: {}",
typeid(T).name(), numInstances, std::generic_category().message(errno)));
if constexpr (Misc::IS_BIG_ENDIAN)
for (std::size_t i = 0; i < numInstances; i++)
Misc::swapEndiannessInplace(dest[i]);