diff --git a/Assets/Tests/InputSystem/CoreTests_Actions.cs b/Assets/Tests/InputSystem/CoreTests_Actions.cs index 73ea288d4e..4c5004b6df 100644 --- a/Assets/Tests/InputSystem/CoreTests_Actions.cs +++ b/Assets/Tests/InputSystem/CoreTests_Actions.cs @@ -1763,6 +1763,8 @@ public void Actions_CanRecordActions() using (var trace = new InputActionTrace()) { + Assert.That(trace.buffer.capacityInBytes, Is.Zero); + action.performed += trace.RecordAction; var state = new GamepadState {leftStick = new Vector2(0.123f, 0.234f)}; @@ -1772,6 +1774,7 @@ public void Actions_CanRecordActions() InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.W), 0.0987); InputSystem.Update(); + Assert.That(trace.buffer.capacityInBytes, Is.EqualTo(2048)); // Default capacity increment. Assert.That(trace.count, Is.EqualTo(3)); var events = trace.ToArray(); diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 6fba6b032f..50a3ddb146 100755 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -32,6 +32,8 @@ however, it has to be formatted properly to pass verification tests. - Improved performance of `Touch.activeTouches` (most notably, a lot of time was spent in endlessly repetitive safety checks). - Fixed `EnhancedTouch` APIs not indicating that they need to be enabled with `EnhancedTouchSupport.Enable()`. - The APIs now throw `InvalidOperationException` when used without being enabled. +- Fixed memory corruption in `InputEventTrace.AllocateEvent` ([case 1262496](https://issuetracker.unity3d.com/issues/input-system-crash-with-various-stack-traces-when-using-inputactiontrace-dot-subscribetoall)) + * Manifested itself, for example, as crashes when using `InputActionTrace.SubscribeToAll`. - AxisControls and Vector2Controls' X and Y subcontrols on XR devices now have a minimum range of -1 and a maximum range of 1. This means they can now properly respond to modifiers and interactions in the binding system. #### Actions diff --git a/Packages/com.unity.inputsystem/InputSystem/Events/InputEventBuffer.cs b/Packages/com.unity.inputsystem/InputSystem/Events/InputEventBuffer.cs index f41c68b248..6b79af563b 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Events/InputEventBuffer.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Events/InputEventBuffer.cs @@ -151,25 +151,25 @@ public void AppendEvent(InputEvent* eventPtr, int capacityIncrementInBytes = 204 var alignedSizeInBytes = sizeInBytes.AlignToMultipleOf(InputEvent.kAlignment); // See if we need to enlarge our buffer. + var necessaryCapacity = m_SizeInBytes + alignedSizeInBytes; var currentCapacity = capacityInBytes; - if (currentCapacity < alignedSizeInBytes) + if (currentCapacity < necessaryCapacity) { // Yes, so reallocate. - var newCapacity = Math.Max(currentCapacity + capacityIncrementInBytes, - currentCapacity + alignedSizeInBytes); - var newSize = this.sizeInBytes + newCapacity; - if (newSize > int.MaxValue) + + var newCapacity = necessaryCapacity.AlignToMultipleOf(capacityIncrementInBytes); + if (newCapacity > int.MaxValue) throw new NotImplementedException("NativeArray long support"); var newBuffer = - new NativeArray((int)newSize, Allocator.Persistent, NativeArrayOptions.ClearMemory); + new NativeArray((int)newCapacity, Allocator.Persistent, NativeArrayOptions.ClearMemory); if (m_Buffer.IsCreated) + { UnsafeUtility.MemCpy(newBuffer.GetUnsafePtr(), m_Buffer.GetUnsafeReadOnlyPtr(), this.sizeInBytes); - else - m_SizeInBytes = 0; + if (m_WeOwnTheBuffer) + m_Buffer.Dispose(); + } - if (m_WeOwnTheBuffer) - m_Buffer.Dispose(); m_Buffer = newBuffer; m_WeOwnTheBuffer = true; } diff --git a/Packages/com.unity.inputsystem/InputSystem/Utilities/NumberHelpers.cs b/Packages/com.unity.inputsystem/InputSystem/Utilities/NumberHelpers.cs index 2cec9fb339..c497941b86 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Utilities/NumberHelpers.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Utilities/NumberHelpers.cs @@ -13,6 +13,15 @@ public static int AlignToMultipleOf(this int number, int alignment) return number + alignment - remainder; } + public static long AlignToMultipleOf(this long number, long alignment) + { + var remainder = number % alignment; + if (remainder == 0) + return number; + + return number + alignment - remainder; + } + public static uint AlignToMultipleOf(this uint number, uint alignment) { var remainder = number % alignment;