From 5eb057f422ac316cd1b943f6cd00aabc673dc238 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 3 Dec 2018 22:50:16 -0500 Subject: [PATCH] kernel/object: Amend handle types to distinguish between readable and writable events Two kernel object should absolutely never have the same handle ID type. This can cause incorrect behavior when it comes to retrieving object types from the handle table. In this case it allows converting a WritableEvent into a ReadableEvent and vice-versa, which is undefined behavior, since the object types are not the same. This also corrects ClearEvent() to check both kernel types like the kernel itself does. --- src/core/hle/kernel/object.cpp | 3 ++- src/core/hle/kernel/object.h | 3 ++- src/core/hle/kernel/readable_event.h | 2 +- src/core/hle/kernel/svc.cpp | 19 +++++++++++++------ src/core/hle/kernel/writable_event.h | 2 +- src/yuzu/debugger/wait_tree.cpp | 2 +- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp index d87a62bb9..bb1b68778 100644 --- a/src/core/hle/kernel/object.cpp +++ b/src/core/hle/kernel/object.cpp @@ -13,7 +13,7 @@ Object::~Object() = default; bool Object::IsWaitable() const { switch (GetHandleType()) { - case HandleType::Event: + case HandleType::ReadableEvent: case HandleType::Thread: case HandleType::Timer: case HandleType::ServerPort: @@ -21,6 +21,7 @@ bool Object::IsWaitable() const { return true; case HandleType::Unknown: + case HandleType::WritableEvent: case HandleType::SharedMemory: case HandleType::Process: case HandleType::AddressArbiter: diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 69082ce3e..f1606a204 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h @@ -19,7 +19,8 @@ using Handle = u32; enum class HandleType : u32 { Unknown, - Event, + WritableEvent, + ReadableEvent, SharedMemory, Thread, Process, diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h index b1f1f4871..867ff3051 100644 --- a/src/core/hle/kernel/readable_event.h +++ b/src/core/hle/kernel/readable_event.h @@ -29,7 +29,7 @@ public: return reset_type; } - static const HandleType HANDLE_TYPE = HandleType::Event; + static const HandleType HANDLE_TYPE = HandleType::ReadableEvent; HandleType GetHandleType() const override { return HANDLE_TYPE; } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 948989b31..d2d893992 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1575,14 +1575,21 @@ static ResultCode ClearEvent(Handle handle) { LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); - SharedPtr evt = handle_table.Get(handle); - if (evt == nullptr) { - LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); - return ERR_INVALID_HANDLE; + + auto writable_event = handle_table.Get(handle); + if (writable_event) { + writable_event->Clear(); + return RESULT_SUCCESS; } - evt->Clear(); - return RESULT_SUCCESS; + auto readable_event = handle_table.Get(handle); + if (readable_event) { + readable_event->Clear(); + return RESULT_SUCCESS; + } + + LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); + return ERR_INVALID_HANDLE; } static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) { diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h index fc57d18d7..8fa8d68ee 100644 --- a/src/core/hle/kernel/writable_event.h +++ b/src/core/hle/kernel/writable_event.h @@ -39,7 +39,7 @@ public: return name; } - static const HandleType HANDLE_TYPE = HandleType::Event; + static const HandleType HANDLE_TYPE = HandleType::WritableEvent; HandleType GetHandleType() const override { return HANDLE_TYPE; } diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 96c57fe97..f9c18ede4 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -153,7 +153,7 @@ QString WaitTreeWaitObject::GetText() const { std::unique_ptr WaitTreeWaitObject::make(const Kernel::WaitObject& object) { switch (object.GetHandleType()) { - case Kernel::HandleType::Event: + case Kernel::HandleType::ReadableEvent: return std::make_unique(static_cast(object)); case Kernel::HandleType::Timer: return std::make_unique(static_cast(object));