diff options
| author | 2020-12-12 06:37:08 -0500 | |
|---|---|---|
| committer | 2020-12-12 07:05:38 -0500 | |
| commit | 1c773c0869b95d749613e08301637a0b80f1bbc9 (patch) | |
| tree | d2a3f0736acd3fd0e043cbeae58ed5b7183344e9 | |
| parent | Merge pull request #5183 from lioncash/alias2 (diff) | |
| download | yuzu-1c773c0869b95d749613e08301637a0b80f1bbc9.tar.gz yuzu-1c773c0869b95d749613e08301637a0b80f1bbc9.tar.xz yuzu-1c773c0869b95d749613e08301637a0b80f1bbc9.zip | |
controllers/npad: Validate device handles before use
Some games such as NEKOPARA Vol. 3 send invalid device handles when calling InitializeVibrationDevice. Introduce a check to validate the device handle before use.
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 41 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 4 |
2 files changed, 45 insertions, 0 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 66c4fe60a..f6a0770bf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -116,6 +116,31 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 116 | } | 116 | } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | bool Controller_NPad::IsNpadIdValid(u32 npad_id) { | ||
| 120 | switch (npad_id) { | ||
| 121 | case 0: | ||
| 122 | case 1: | ||
| 123 | case 2: | ||
| 124 | case 3: | ||
| 125 | case 4: | ||
| 126 | case 5: | ||
| 127 | case 6: | ||
| 128 | case 7: | ||
| 129 | case NPAD_UNKNOWN: | ||
| 130 | case NPAD_HANDHELD: | ||
| 131 | return true; | ||
| 132 | default: | ||
| 133 | LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id); | ||
| 134 | return false; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { | ||
| 139 | return IsNpadIdValid(device_handle.npad_id) && | ||
| 140 | device_handle.npad_type < NpadType::MaxNpadType && | ||
| 141 | device_handle.device_index < DeviceIndex::MaxDeviceIndex; | ||
| 142 | } | ||
| 143 | |||
| 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} | 144 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} |
| 120 | 145 | ||
| 121 | Controller_NPad::~Controller_NPad() { | 146 | Controller_NPad::~Controller_NPad() { |
| @@ -742,6 +767,10 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size | |||
| 742 | 767 | ||
| 743 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, | 768 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, |
| 744 | const VibrationValue& vibration_value) { | 769 | const VibrationValue& vibration_value) { |
| 770 | if (!IsDeviceHandleValid(vibration_device_handle)) { | ||
| 771 | return; | ||
| 772 | } | ||
| 773 | |||
| 745 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | 774 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { |
| 746 | return; | 775 | return; |
| 747 | } | 776 | } |
| @@ -798,12 +827,20 @@ void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibrat | |||
| 798 | 827 | ||
| 799 | Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( | 828 | Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( |
| 800 | const DeviceHandle& vibration_device_handle) const { | 829 | const DeviceHandle& vibration_device_handle) const { |
| 830 | if (!IsDeviceHandleValid(vibration_device_handle)) { | ||
| 831 | return {}; | ||
| 832 | } | ||
| 833 | |||
| 801 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | 834 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 802 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | 835 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 803 | return latest_vibration_values[npad_index][device_index]; | 836 | return latest_vibration_values[npad_index][device_index]; |
| 804 | } | 837 | } |
| 805 | 838 | ||
| 806 | void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { | 839 | void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { |
| 840 | if (!IsDeviceHandleValid(vibration_device_handle)) { | ||
| 841 | return; | ||
| 842 | } | ||
| 843 | |||
| 807 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | 844 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 808 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | 845 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 809 | InitializeVibrationDeviceAtIndex(npad_index, device_index); | 846 | InitializeVibrationDeviceAtIndex(npad_index, device_index); |
| @@ -824,6 +861,10 @@ void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { | |||
| 824 | } | 861 | } |
| 825 | 862 | ||
| 826 | bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { | 863 | bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { |
| 864 | if (!IsDeviceHandleValid(vibration_device_handle)) { | ||
| 865 | return false; | ||
| 866 | } | ||
| 867 | |||
| 827 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | 868 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 828 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | 869 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 829 | return vibration_devices_mounted[npad_index][device_index]; | 870 | return vibration_devices_mounted[npad_index][device_index]; |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 96f319294..9fac00231 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -56,12 +56,14 @@ public: | |||
| 56 | JoyconLeft = 6, | 56 | JoyconLeft = 6, |
| 57 | JoyconRight = 7, | 57 | JoyconRight = 7, |
| 58 | Pokeball = 9, | 58 | Pokeball = 9, |
| 59 | MaxNpadType = 10, | ||
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| 61 | enum class DeviceIndex : u8 { | 62 | enum class DeviceIndex : u8 { |
| 62 | Left = 0, | 63 | Left = 0, |
| 63 | Right = 1, | 64 | Right = 1, |
| 64 | None = 2, | 65 | None = 2, |
| 66 | MaxDeviceIndex = 3, | ||
| 65 | }; | 67 | }; |
| 66 | 68 | ||
| 67 | enum class GyroscopeZeroDriftMode : u32 { | 69 | enum class GyroscopeZeroDriftMode : u32 { |
| @@ -213,6 +215,8 @@ public: | |||
| 213 | static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); | 215 | static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); |
| 214 | static std::size_t NPadIdToIndex(u32 npad_id); | 216 | static std::size_t NPadIdToIndex(u32 npad_id); |
| 215 | static u32 IndexToNPad(std::size_t index); | 217 | static u32 IndexToNPad(std::size_t index); |
| 218 | static bool IsNpadIdValid(u32 npad_id); | ||
| 219 | static bool IsDeviceHandleValid(const DeviceHandle& device_handle); | ||
| 216 | 220 | ||
| 217 | private: | 221 | private: |
| 218 | struct CommonHeader { | 222 | struct CommonHeader { |