diff --git a/core/libs/prx/libc/CMakeLists.txt b/core/libs/prx/libc/CMakeLists.txt index 15a54b425..4e047cc0b 100644 --- a/core/libs/prx/libc/CMakeLists.txt +++ b/core/libs/prx/libc/CMakeLists.txt @@ -452,6 +452,15 @@ if(BUILD_TESTING) set_tests_properties(guest_wcsrtombs_s PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_overflow_error_tests ${LIBS_INCLUDE_DIR}/tests/GuestOverflowError.cpp) + target_include_directories(guest_overflow_error_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_overflow_error_tests PRIVATE libc) + configure_windows_unwind(guest_overflow_error_tests) + add_test(NAME guest_overflow_error COMMAND guest_overflow_error_tests) + if(WIN32) + set_tests_properties(guest_overflow_error PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() if(UNIX) add_test_executable(exception_runtime_tests ${LIBS_INCLUDE_DIR}/tests/ExceptionRuntime.cpp) target_include_directories(exception_runtime_tests PRIVATE ${LIBS_INCLUDE_DIR}) diff --git a/core/libs/prx/libc/src/exception/StandardExceptions.cpp b/core/libs/prx/libc/src/exception/StandardExceptions.cpp index cef6c4e56..9e425979f 100644 --- a/core/libs/prx/libc/src/exception/StandardExceptions.cpp +++ b/core/libs/prx/libc/src/exception/StandardExceptions.cpp @@ -291,6 +291,10 @@ void APS5_VABI _ZNSt11range_errorD1Ev_nid_postfix(LibcException::ExceptionObject void APS5_VABI _ZNSt11range_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt11range_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } +LibcException::TypeRecord _ZTISt14overflow_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St14overflow_error", &_ZTISt13runtime_error_nid_postfix}; +LibcException::ExceptionVtable _ZTVSt14overflow_error_nid_postfix {0, &_ZTISt14overflow_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; +void APS5_VABI _ZNSt14overflow_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } + LibcException::TypeRecord _ZTINSt8ios_base7failureE_nid_postfix {LibcException::SingleTypeVtable + 2, "NSt8ios_base7failureE", &_ZTISt12system_error_nid_postfix}; LibcException::ExceptionVtable _ZTVNSt8ios_base7failureE_nid_postfix {0, &_ZTINSt8ios_base7failureE_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt8ios_base7failureD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } diff --git a/core/libs/tests/GuestOverflowError.cpp b/core/libs/tests/GuestOverflowError.cpp new file mode 100644 index 000000000..9bfb21a08 --- /dev/null +++ b/core/libs/tests/GuestOverflowError.cpp @@ -0,0 +1,38 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include + +struct TypeRecord { const void* const* vtable; const char* name; const TypeRecord* base; }; +struct Object { const void* vtable; const char* message; }; +struct Vtable { std::ptrdiff_t offset; const TypeRecord* type; const void* destroy; const void* deleteObject; const void* what; }; + +extern "C" { +extern const TypeRecord _ZTISt13runtime_error_nid_postfix; +extern const TypeRecord _ZTISt14overflow_error_nid_postfix; +extern const Vtable _ZTVSt13runtime_error_nid_postfix; +extern const Vtable _ZTVSt14overflow_error_nid_postfix; +void APS5_VABI _ZNSt13runtime_errorC1EPKc_nid_postfix(Object*, const char*); +void APS5_VABI _ZNSt14overflow_errorD1Ev_nid_postfix(Object*); +} + +static void Require(bool value) { if (!value) std::abort(); } + +int main() { + const auto& type = _ZTISt14overflow_error_nid_postfix; + const auto& runtimeType = _ZTISt13runtime_error_nid_postfix; + Require(std::strcmp(type.name, "St14overflow_error") == 0); + Require(type.base == &runtimeType && type.vtable == runtimeType.vtable); + const auto& table = _ZTVSt14overflow_error_nid_postfix; + const auto& runtimeTable = _ZTVSt13runtime_error_nid_postfix; + Require(table.offset == 0 && table.type == &type); + Require(table.destroy == runtimeTable.destroy && table.deleteObject == runtimeTable.deleteObject && table.what == runtimeTable.what); + Object object{}; + _ZNSt13runtime_errorC1EPKc_nid_postfix(&object, "value too large"); + Require(object.message != nullptr && std::strcmp(object.message, "value too large") == 0); + _ZNSt14overflow_errorD1Ev_nid_postfix(&object); + Require(object.message == nullptr); + _ZNSt14overflow_errorD1Ev_nid_postfix(&object); + Require(object.message == nullptr); + return 0; +}