diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 3b8a3c3344..90a8418cf6 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -591,10 +591,42 @@ void fmt_class_string::format(std::string& out, u64 arg) namespace fmt { - [[noreturn]] void raw_verify_error(std::source_location loc, const char8_t* msg) + [[noreturn]] void raw_verify_error(std::source_location loc, const char8_t* msg, usz object) { std::string out; - fmt::append(out, "%s%s", msg ? msg : u8"Verification failed", loc); + fmt::append(out, "%s (object: 0x%x)%s", msg ? msg : u8"Verification failed", object, loc); + thread_ctrl::emergency_exit(out); + } + + [[noreturn]] void raw_range_error(std::source_location loc, std::string_view index, usz container_size) + { + std::string out; + + if (container_size != umax) + { + fmt::append(out, "Range check failed (index: %s, container_size: %u)%s", index, container_size, loc); + } + else + { + fmt::append(out, "Range check failed (index: %s)%s", index, loc); + } + + thread_ctrl::emergency_exit(out); + } + + [[noreturn]] void raw_range_error(std::source_location loc, usz index, usz container_size) + { + std::string out; + + if (container_size != umax) + { + fmt::append(out, "Range check failed (index: %u, container_size: %u)%s", index, container_size, loc); + } + else + { + fmt::append(out, "Range check failed (index: %u)%s", index, loc); + } + thread_ctrl::emergency_exit(out); } diff --git a/rpcs3/util/types.hpp b/rpcs3/util/types.hpp index ad7a740301..c686352c2e 100644 --- a/rpcs3/util/types.hpp +++ b/rpcs3/util/types.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #if defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(__amd64__) @@ -912,7 +913,25 @@ using const_str = const_str_t<>; namespace fmt { - [[noreturn]] void raw_verify_error(std::source_location loc, const char8_t* msg); + [[noreturn]] void raw_verify_error(std::source_location loc, const char8_t* msg, usz object); + [[noreturn]] void raw_range_error(std::source_location loc, std::string_view index, usz container_size); + [[noreturn]] void raw_range_error(std::source_location loc, usz index, usz container_size); +} + +// No full implementation to ease on header weight +template +std::conditional_t>, usz, std::string_view> format_object_simplified(const T& obj) +{ + using type = std::remove_cvref_t; + + if constexpr (std::is_integral_v || std::is_same_v || std::is_same_v) + { + return obj; + } + else + { + return std::string_view{}; + } } template @@ -923,7 +942,7 @@ constexpr decltype(auto) ensure(T&& arg, const_str msg = const_str(), std::sourc return std::forward(arg); } - fmt::raw_verify_error(src_loc, msg); + fmt::raw_verify_error(src_loc, msg, 0); } template requires (std::is_invocable_v) @@ -934,7 +953,7 @@ constexpr decltype(auto) ensure(T&& arg, F&& pred, const_str msg = const_str(), return std::forward(arg); } - fmt::raw_verify_error(src_loc, msg); + fmt::raw_verify_error(src_loc, msg, 0); } // narrow() function details @@ -1015,7 +1034,7 @@ template // Narrow check if (narrow_impl::test(value)) [[unlikely]] { - fmt::raw_verify_error(src_loc, u8"Narrowing error"); + fmt::raw_verify_error(src_loc, u8"Narrowing error", +value); } return static_cast(value); @@ -1046,7 +1065,7 @@ template requires requires (CT&& x) { std::size(x); st const std::make_unsigned_t> idx = index; const u32 csz = ::size32(container, src_loc); if (csz <= idx) [[unlikely]] - fmt::raw_verify_error(src_loc, u8"Out of range"); + fmt::raw_range_error(src_loc, format_object_simplified(index), csz); auto it = std::begin(std::forward(container)); std::advance(it, idx); return *it; @@ -1057,8 +1076,11 @@ template requires requires (CT&& x, T&& y) { x.count(y { // Associative container const auto found = container.find(std::forward(index)); + usz csv = umax; + if constexpr ((requires () { container.size(); })) + csv = container.size(); if (found == container.end()) [[unlikely]] - fmt::raw_verify_error(src_loc, u8"Out of range"); + fmt::raw_range_error(src_loc, format_object_simplified(index), csv); return found->second; }