mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-02 13:01:27 +12:00
fs::file: always use strict reading mode for large reads (#11206)
This commit is contained in:
parent
f910a152f1
commit
f16949c292
8 changed files with 55 additions and 69 deletions
|
@ -205,8 +205,6 @@ namespace fs
|
|||
{
|
||||
std::unique_ptr<file_base> m_file{};
|
||||
|
||||
bool strict_read_check(u64 size, u64 type_size) const;
|
||||
|
||||
public:
|
||||
// Default constructor
|
||||
file() = default;
|
||||
|
@ -281,6 +279,9 @@ namespace fs
|
|||
return m_file->sync();
|
||||
}
|
||||
|
||||
// Check if the handle is capable of reading (size * type_size) of bytes at the time of calling
|
||||
bool strict_read_check(u64 size, u64 type_size = 1) const;
|
||||
|
||||
// Read the data from the file and return the amount of data written in buffer
|
||||
u64 read(void* buffer, u64 count,
|
||||
u32 line = __builtin_LINE(),
|
||||
|
@ -337,8 +338,8 @@ namespace fs
|
|||
}
|
||||
|
||||
// Write std::basic_string unconditionally
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const std::basic_string<T>& str,
|
||||
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
const file& write(const std::basic_string<T>& str,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
|
@ -349,8 +350,8 @@ namespace fs
|
|||
}
|
||||
|
||||
// Write POD unconditionally
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const T& data,
|
||||
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
const file& write(const T& data,
|
||||
pod_tag_t = pod_tag,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
|
@ -362,8 +363,8 @@ namespace fs
|
|||
}
|
||||
|
||||
// Write POD std::vector unconditionally
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const std::vector<T>& vec,
|
||||
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
const file& write(const std::vector<T>& vec,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
|
@ -373,84 +374,69 @@ namespace fs
|
|||
return *this;
|
||||
}
|
||||
|
||||
// Read std::basic_string, size must be set by resize() method
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
return read(&str[0], str.size() * sizeof(T), line, col, file, func) == str.size() * sizeof(T);
|
||||
}
|
||||
|
||||
// Read std::basic_string
|
||||
template <bool IsStrict = false, typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str, usz _size,
|
||||
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
bool read(std::basic_string<T>& str, usz _size = umax,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
if (!_size) return true;
|
||||
|
||||
if constexpr (IsStrict)
|
||||
if (_size != umax)
|
||||
{
|
||||
// If _size arg is too high std::bad_alloc may happen in resize and then we cannot error check
|
||||
if (!strict_read_check(_size, sizeof(T))) return false;
|
||||
// If _size arg is too high std::bad_alloc may happen during resize and then we cannot error check
|
||||
if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(_size, sizeof(T)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
str.resize(_size);
|
||||
}
|
||||
|
||||
str.resize(_size);
|
||||
return read(str.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
|
||||
return read(str.data(), sizeof(T) * str.size(), line, col, file, func) == sizeof(T) * str.size();
|
||||
}
|
||||
|
||||
// Read POD, sizeof(T) is used
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(T& data,
|
||||
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
bool read(T& data,
|
||||
pod_tag_t = pod_tag,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
return read(&data, sizeof(T), line, col, file, func) == sizeof(T);
|
||||
}
|
||||
|
||||
// Read POD std::vector, size must be set by resize() method
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
return read(vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size();
|
||||
return read(std::addressof(data), sizeof(T), line, col, file, func) == sizeof(T);
|
||||
}
|
||||
|
||||
// Read POD std::vector
|
||||
template <bool IsStrict = false, typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, usz _size,
|
||||
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
bool read(std::vector<T>& vec, usz _size = umax,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
if (!_size) return true;
|
||||
|
||||
if constexpr (IsStrict)
|
||||
if (_size != umax)
|
||||
{
|
||||
if (!strict_read_check(_size, sizeof(T))) return false;
|
||||
// If _size arg is too high std::bad_alloc may happen during resize and then we cannot error check
|
||||
if ((_size >= 0x10'0000 / sizeof(T)) && !strict_read_check(_size, sizeof(T)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vec.resize(_size);
|
||||
}
|
||||
|
||||
vec.resize(_size);
|
||||
return read(vec.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
|
||||
return read(vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size();
|
||||
}
|
||||
|
||||
// Read POD (experimental)
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, T> read(
|
||||
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
T read(
|
||||
pod_tag_t = pod_tag,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
|
@ -472,13 +458,13 @@ namespace fs
|
|||
{
|
||||
std::basic_string<T> result;
|
||||
result.resize(size() / sizeof(T));
|
||||
if (seek(0), !read(result, file, func, line, col)) xfail({line, col, file, func});
|
||||
if (seek(0), !read(result, result.size(), file, func, line, col)) xfail({line, col, file, func});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read full file to std::vector
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, std::vector<T>> to_vector(
|
||||
template<typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
|
||||
std::vector<T> to_vector(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
|
@ -486,7 +472,7 @@ namespace fs
|
|||
{
|
||||
std::vector<T> result;
|
||||
result.resize(size() / sizeof(T));
|
||||
if (seek(0), !read(result, file, func, line, col)) xfail({line, col, file, func});
|
||||
if (seek(0), !read(result, result.size(), file, func, line, col)) xfail({line, col, file, func});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue