diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index ecbe75a09e..70e3622787 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -15,6 +15,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed memory leak when the OnScreenStick component was destroyed [ISXB-1070](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1070). Contribution by [LukeUnityDev](https://github.com/LukeUnityDev). - Fixed Action Maps contextual menu in Action Editor UI that occasionally displays unrelated items. - Fixed "MissingReferenceException" errors when closing an in-game dropdown field [ISXB-1081](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1081). +- Fixed potential crash on Mac when using stale references to deleted InputDevice objects [ISXB-606](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-606). ### Changed - Renamed editor Resources directories to PackageResources to fix package validation warnings. diff --git a/Packages/com.unity.inputsystem/InputSystem/Controls/InputControl.cs b/Packages/com.unity.inputsystem/InputSystem/Controls/InputControl.cs index 9e5bdf2ae2..1f5ec6adec 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Controls/InputControl.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Controls/InputControl.cs @@ -1232,6 +1232,20 @@ internal unsafe ref readonly TValue unprocessedValue if (InputUpdate.s_LatestUpdateType.IsEditorUpdate()) return ref ReadUnprocessedStateInEditor(); #endif + // Case ISXB-606 + // If an object reference has the underlying object deleted then a device can go + // away which means that the underlying state buffers will have been resized. + // + // The currentStatePtr accessor uses GetDeviceIndex() to index into the state + // buffers but this index can then be out of bounds. + // + // InputStateBuffers.Get{Front,Back}Buffer() now check for the requested index being + // in-bounds and return null if not - check that here to avoid null derefence later. + // + if (currentStatePtr == null) + { + return ref m_UnprocessedCachedValue; + } if ( // if feature is disabled we re-evaluate every call diff --git a/Packages/com.unity.inputsystem/InputSystem/State/InputStateBuffers.cs b/Packages/com.unity.inputsystem/InputSystem/State/InputStateBuffers.cs index 0dc2a0e63c..8bcffd38b4 100644 --- a/Packages/com.unity.inputsystem/InputSystem/State/InputStateBuffers.cs +++ b/Packages/com.unity.inputsystem/InputSystem/State/InputStateBuffers.cs @@ -60,27 +60,34 @@ internal struct DoubleBuffers // buffer and [deviceIndex*2+1] is back buffer. Each device // has its buffers swapped individually with SwapDeviceBuffers(). public void** deviceToBufferMapping; + public int deviceCount; public bool valid => deviceToBufferMapping != null; public void SetFrontBuffer(int deviceIndex, void* ptr) { - deviceToBufferMapping[deviceIndex * 2] = ptr; + if (deviceIndex < deviceCount) + deviceToBufferMapping[deviceIndex * 2] = ptr; } public void SetBackBuffer(int deviceIndex, void* ptr) { - deviceToBufferMapping[deviceIndex * 2 + 1] = ptr; + if (deviceIndex < deviceCount) + deviceToBufferMapping[deviceIndex * 2 + 1] = ptr; } public void* GetFrontBuffer(int deviceIndex) { - return deviceToBufferMapping[deviceIndex * 2]; + if (deviceIndex < deviceCount) + return deviceToBufferMapping[deviceIndex * 2]; + return null; } public void* GetBackBuffer(int deviceIndex) { - return deviceToBufferMapping[deviceIndex * 2 + 1]; + if (deviceIndex < deviceCount) + return deviceToBufferMapping[deviceIndex * 2 + 1]; + return null; } public void SwapBuffers(int deviceIndex) @@ -197,7 +204,11 @@ private static DoubleBuffers SetUpDeviceToBufferMappings(int deviceCount, ref by var mappings = (void**)(bufferPtr + sizePerBuffer * 2); // Put mapping table at end. bufferPtr += sizePerBuffer * 2 + mappingTableSizePerBuffer; - var buffers = new DoubleBuffers {deviceToBufferMapping = mappings}; + var buffers = new DoubleBuffers + { + deviceToBufferMapping = mappings, + deviceCount = deviceCount + }; for (var i = 0; i < deviceCount; ++i) {