From 68718e76b1b3e04ed3a3db2d6036753d93e26a83 Mon Sep 17 00:00:00 2001 From: Tom Erez Date: Thu, 15 Sep 2022 10:25:33 -0700 Subject: [PATCH] Ensure that memory allocated by `mju_malloc` is freed by `mju_free`. Previously, `vfs->filedata` memory was allocated via `mju_malloc` in C and released using `Marshal.FreeHGlobal` in C#. In 5cc73c30bfdc34e7b0f612e2ba25a7cdfc4a19ba, `mju_malloc` started returning 64-byte aligned pointers, which should not be freed by a deallocator that isn't aware of this alignment. Fixes #479. PiperOrigin-RevId: 474596441 Change-Id: I8a8383c7eaa2c1ec516d81f92a2f90e7aedfe2ee --- unity/Runtime/Tools/MjVfs.cs | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/unity/Runtime/Tools/MjVfs.cs b/unity/Runtime/Tools/MjVfs.cs index 2449b1f6..f46a9a88 100644 --- a/unity/Runtime/Tools/MjVfs.cs +++ b/unity/Runtime/Tools/MjVfs.cs @@ -56,7 +56,8 @@ public sealed class MjVfs : IDisposable { if (fileIndex < 0) { throw new IndexOutOfRangeException("VFS didn't properly create the empty file."); } - SetFileContents(fileIndex, contents); + var contents_bytes = Encoding.UTF8.GetBytes(contents); + Marshal.Copy(contents_bytes, 0, Data.filedata[fileIndex], contents_bytes.Length); } // Searches the VFS for the specified file and returns its index. @@ -82,17 +83,10 @@ public sealed class MjVfs : IDisposable { return model; } - private unsafe void SetFileContents(int fileIndex, string contents) { - var data = Data; - Marshal.FreeHGlobal(data.filedata[fileIndex]); - data.filedata[fileIndex] = Marshal.StringToHGlobalAnsi(contents); - Data = data; - } - - public MjVfs() { - _managedVfs = new _mjVFS(); + public unsafe MjVfs() { _unmanagedVfs = Marshal.AllocHGlobal(Marshal.SizeOf(_managedVfs)); - Marshal.StructureToPtr(_managedVfs, _unmanagedVfs, true); + mj_defaultVFS(_unmanagedVfs.ToPointer()); + _managedVfs = (_mjVFS)Marshal.PtrToStructure(_unmanagedVfs, typeof(_mjVFS)); } ~MjVfs() { @@ -104,13 +98,9 @@ public sealed class MjVfs : IDisposable { ReleaseUnmanagedMemory(); } - private void ReleaseUnmanagedMemory() { + private unsafe void ReleaseUnmanagedMemory() { if (_unmanagedVfs != IntPtr.Zero) { - var data = Data; - for (var fileIndex = 0; fileIndex < data.nfile; ++fileIndex) { - Marshal.FreeHGlobal(data.filedata[fileIndex]); - } - + mj_deleteVFS(_unmanagedVfs.ToPointer()); Marshal.FreeHGlobal(_unmanagedVfs); _unmanagedVfs = IntPtr.Zero; }