From 6fe51f970501fe732276c17ed0dacb564b92a73d Mon Sep 17 00:00:00 2001
From: riperiperi <rhy3756547@hotmail.com>
Date: Sat, 9 Jun 2018 01:15:02 +0100
Subject: [PATCH] ReadBytes function in AMemory, with cleaner range check.
 (#136)

---
 ChocolArm64/Memory/AMemory.cs                 | 20 +++++++++++
 ChocolArm64/Memory/AMemoryHelper.cs           | 12 -------
 Ryujinx.Core/Gpu/NvGpuVmm.cs                  |  2 +-
 Ryujinx.Core/OsHle/Kernel/SvcSystem.cs        |  2 +-
 .../OsHle/Services/Am/IStorageAccessor.cs     |  2 +-
 .../OsHle/Services/Aud/IAudioDevice.cs        |  4 +--
 Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs  |  3 +-
 Ryujinx.Core/OsHle/Services/Bsd/IClient.cs    | 35 ++++++++-----------
 Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs   |  2 +-
 Ryujinx.Core/OsHle/Services/Lm/ILogger.cs     |  3 +-
 .../Services/Set/ISystemSettingsServer.cs     |  4 +--
 .../OsHle/Services/Vi/IHOSBinderDriver.cs     |  4 +--
 12 files changed, 46 insertions(+), 47 deletions(-)

diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs
index c24a9e8ef9..e7d46565f8 100644
--- a/ChocolArm64/Memory/AMemory.cs
+++ b/ChocolArm64/Memory/AMemory.cs
@@ -301,6 +301,15 @@ namespace ChocolArm64.Memory
             return *((ulong*)(RamPtr + (uint)Position));
         }
 
+        public byte[] ReadBytes(long Position, long Size)
+        {
+            EnsureRangeIsValid(Position, Size, AMemoryPerm.Read);
+
+            byte[] Result = new byte[Size];
+            Marshal.Copy((IntPtr)(RamPtr + (uint)Position), Result, 0, (int)Size);
+            return Result;
+        }
+
         public Vector128<float> ReadVector8Unchecked(long Position)
         {
             if (Sse2.IsSupported)
@@ -611,6 +620,17 @@ namespace ChocolArm64.Memory
             }
         }
 
+        private void EnsureRangeIsValid(long Position, long Size, AMemoryPerm Perm)
+        {
+            long EndPos = (Position + Size);
+            Position = Position & ~AMemoryMgr.PageMask; //check base of each page
+            while (Position < EndPos)
+            {
+                EnsureAccessIsValid(Position, Perm);
+                Position += AMemoryMgr.PageSize;
+            }
+        }
+
         public void Dispose()
         {
             Dispose(true);
diff --git a/ChocolArm64/Memory/AMemoryHelper.cs b/ChocolArm64/Memory/AMemoryHelper.cs
index 1e3462985b..c0ade89ce0 100644
--- a/ChocolArm64/Memory/AMemoryHelper.cs
+++ b/ChocolArm64/Memory/AMemoryHelper.cs
@@ -22,18 +22,6 @@ namespace ChocolArm64.Memory
             }
         }
 
-        public static byte[] ReadBytes(AMemory Memory, long Position, long Size)
-        {
-            byte[] Data = new byte[Size];
-
-            for (long Offs = 0; Offs < Size; Offs++)
-            {
-                Data[Offs] = (byte)Memory.ReadByte(Position + Offs);
-            }
-
-            return Data;
-        }
-
         public static void WriteBytes(AMemory Memory, long Position, byte[] Data)
         {
             for (int Offs = 0; Offs < Data.Length; Offs++)
diff --git a/Ryujinx.Core/Gpu/NvGpuVmm.cs b/Ryujinx.Core/Gpu/NvGpuVmm.cs
index 1c408964fa..09553b8ada 100644
--- a/Ryujinx.Core/Gpu/NvGpuVmm.cs
+++ b/Ryujinx.Core/Gpu/NvGpuVmm.cs
@@ -330,7 +330,7 @@ namespace Ryujinx.Core.Gpu
         {
             Position = GetPhysicalAddress(Position);
 
-            return AMemoryHelper.ReadBytes(Memory, Position, Size);
+            return Memory.ReadBytes(Position, Size);
         }
 
         public void WriteByte(long Position, byte Value)
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
index 77f35c199c..638625d829 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
@@ -233,7 +233,7 @@ namespace Ryujinx.Core.OsHle.Kernel
         {
             KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
 
-            byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
+            byte[] CmdData = Memory.ReadBytes(CmdPtr, Size);
 
             KSession Session = Process.HandleTable.GetData<KSession>(Handle);
 
diff --git a/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs
index 0e928f6781..4cd1f99b83 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs
@@ -49,7 +49,7 @@ namespace Ryujinx.Core.OsHle.Services.Am
                     Size = MaxSize;
                 }
 
-                byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, Position, Size);
+                byte[] Data = Context.Memory.ReadBytes(Position, Size);
 
                 Buffer.BlockCopy(Data, 0, Storage.Data, (int)WritePosition, (int)Size);
             }
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
index b5de85a133..73916f709c 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
@@ -75,7 +75,7 @@ namespace Ryujinx.Core.OsHle.Services.Aud
             long Position = Context.Request.SendBuff[0].Position;
             long Size     = Context.Request.SendBuff[0].Size;
 
-            byte[] DeviceNameBuffer = AMemoryHelper.ReadBytes(Context.Memory, Position, Size);
+            byte[] DeviceNameBuffer = Context.Memory.ReadBytes(Position, Size);
 
             string DeviceName = Encoding.ASCII.GetString(DeviceNameBuffer);
 
@@ -160,7 +160,7 @@ namespace Ryujinx.Core.OsHle.Services.Aud
 
             (long Position, long Size) = Context.Request.GetBufferType0x21();
 
-            byte[] DeviceNameBuffer = AMemoryHelper.ReadBytes(Context.Memory, Position, Size);
+            byte[] DeviceNameBuffer = Context.Memory.ReadBytes(Position, Size);
 
             string DeviceName = Encoding.UTF8.GetString(DeviceNameBuffer);
 
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
index 09c5050fc0..fba97a3f5a 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
@@ -69,8 +69,7 @@ namespace Ryujinx.Core.OsHle.Services.Aud
                 Context.Memory,
                 Context.Request.SendBuff[0].Position);
 
-            byte[] Buffer = AMemoryHelper.ReadBytes(
-                Context.Memory,
+            byte[] Buffer = Context.Memory.ReadBytes(
                 Data.SampleBufferPtr,
                 Data.SampleBufferSize);
 
diff --git a/Ryujinx.Core/OsHle/Services/Bsd/IClient.cs b/Ryujinx.Core/OsHle/Services/Bsd/IClient.cs
index f26e5ee374..0c0eeb5a3d 100644
--- a/Ryujinx.Core/OsHle/Services/Bsd/IClient.cs
+++ b/Ryujinx.Core/OsHle/Services/Bsd/IClient.cs
@@ -102,9 +102,8 @@ namespace Ryujinx.Core.OsHle.Services.Bsd
             //https://github.com/TuxSH/ftpd/blob/switch_pr/source/ftp.c#L1634
             //https://linux.die.net/man/2/poll
 
-            byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory,
-                                                        Context.Request.SendBuff[0].Position,
-                                                        Context.Request.SendBuff[0].Size);
+            byte[] SentBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[0].Position,
+                                                         Context.Request.SendBuff[0].Size);
 
             int SocketId        = Get32(SentBuffer, 0);
             int RequestedEvents = Get16(SentBuffer, 4);
@@ -152,9 +151,8 @@ namespace Ryujinx.Core.OsHle.Services.Bsd
             int SocketId    = Context.RequestData.ReadInt32();
             int SocketFlags = Context.RequestData.ReadInt32();
 
-            byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory,
-                                                        Context.Request.SendBuff[0].Position,
-                                                        Context.Request.SendBuff[0].Size);
+            byte[] SentBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[0].Position,
+                                                         Context.Request.SendBuff[0].Size);
 
             try
             {
@@ -180,13 +178,11 @@ namespace Ryujinx.Core.OsHle.Services.Bsd
             int SocketId    = Context.RequestData.ReadInt32();
             int SocketFlags = Context.RequestData.ReadInt32();
 
-            byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory,
-                                                        Context.Request.SendBuff[0].Position,
-                                                        Context.Request.SendBuff[0].Size);
+            byte[] SentBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[0].Position,
+                                                         Context.Request.SendBuff[0].Size);
 
-            byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory,
-                                                           Context.Request.SendBuff[1].Position,
-                                                           Context.Request.SendBuff[1].Size);
+            byte[] AddressBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[1].Position,
+                                                            Context.Request.SendBuff[1].Size);
 
             if (!Sockets[SocketId].Handle.Connected)
             {
@@ -291,9 +287,8 @@ namespace Ryujinx.Core.OsHle.Services.Bsd
         {
             int SocketId = Context.RequestData.ReadInt32();
 
-            byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory,
-                                                           Context.Request.SendBuff[0].Position,
-                                                           Context.Request.SendBuff[0].Size);
+            byte[] AddressBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[0].Position,
+                                                            Context.Request.SendBuff[0].Size);
 
             try
             {
@@ -316,9 +311,8 @@ namespace Ryujinx.Core.OsHle.Services.Bsd
         {
             int SocketId = Context.RequestData.ReadInt32();
 
-            byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory,
-                                                           Context.Request.SendBuff[0].Position,
-                                                           Context.Request.SendBuff[0].Size);
+            byte[] AddressBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[0].Position,
+                                                            Context.Request.SendBuff[0].Size);
 
             try
             {
@@ -369,9 +363,8 @@ namespace Ryujinx.Core.OsHle.Services.Bsd
             SocketOptionLevel SocketLevel      = (SocketOptionLevel)Context.RequestData.ReadInt32();
             SocketOptionName  SocketOptionName =  (SocketOptionName)Context.RequestData.ReadInt32();
 
-            byte[] SocketOptionValue = AMemoryHelper.ReadBytes(Context.Memory,
-                                                               Context.Request.PtrBuff[0].Position,
-                                                               Context.Request.PtrBuff[0].Size);
+            byte[] SocketOptionValue = Context.Memory.ReadBytes(Context.Request.PtrBuff[0].Position,
+                                                                Context.Request.PtrBuff[0].Size);
 
             int OptionValue = Get32(SocketOptionValue, 0);
 
diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
index bd7d138fd5..0dd4538555 100644
--- a/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
+++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
@@ -62,7 +62,7 @@ namespace Ryujinx.Core.OsHle.Services.FspSrv
             long Offset = Context.RequestData.ReadInt64();
             long Size   = Context.RequestData.ReadInt64();
 
-            byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, Position, Size);
+            byte[] Data = Context.Memory.ReadBytes(Position, Size);
 
             BaseStream.Seek(Offset, SeekOrigin.Begin);
             BaseStream.Write(Data, 0, (int)Size);
diff --git a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
index c5b6c93130..5109010589 100644
--- a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
+++ b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
@@ -23,8 +23,7 @@ namespace Ryujinx.Core.OsHle.Services.Lm
 
         public long Log(ServiceCtx Context)
         {
-            byte[] LogBuffer = AMemoryHelper.ReadBytes(
-                Context.Memory,
+            byte[] LogBuffer = Context.Memory.ReadBytes(
                 Context.Request.PtrBuff[0].Position,
                 Context.Request.PtrBuff[0].Size);
 
diff --git a/Ryujinx.Core/OsHle/Services/Set/ISystemSettingsServer.cs b/Ryujinx.Core/OsHle/Services/Set/ISystemSettingsServer.cs
index 26d676938e..8209429130 100644
--- a/Ryujinx.Core/OsHle/Services/Set/ISystemSettingsServer.cs
+++ b/Ryujinx.Core/OsHle/Services/Set/ISystemSettingsServer.cs
@@ -97,8 +97,8 @@ namespace Ryujinx.Core.OsHle.Services.Set
             long ReplyPos  = Context.Request.ReceiveBuff[0].Position;
             long ReplySize = Context.Request.ReceiveBuff[0].Size;
 
-            byte[] Class = AMemoryHelper.ReadBytes(Context.Memory, ClassPos, ClassSize);
-            byte[] Name  = AMemoryHelper.ReadBytes(Context.Memory, NamePos, NameSize);
+            byte[] Class = Context.Memory.ReadBytes(ClassPos, ClassSize);
+            byte[] Name  = Context.Memory.ReadBytes(NamePos, NameSize);
 
             string AskedSetting = Encoding.ASCII.GetString(Class).Trim('\0') + "!" + Encoding.ASCII.GetString(Name).Trim('\0');
 
diff --git a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
index c00e247e29..41c3970e75 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
@@ -41,7 +41,7 @@ namespace Ryujinx.Core.OsHle.Services.Vi
             long DataPos  = Context.Request.SendBuff[0].Position;
             long DataSize = Context.Request.SendBuff[0].Size;
 
-            byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, DataSize);
+            byte[] Data = Context.Memory.ReadBytes(DataPos, DataSize);
 
             Data = Parcel.GetParcelData(Data);
 
@@ -55,7 +55,7 @@ namespace Ryujinx.Core.OsHle.Services.Vi
 
             (long DataPos, long DataSize) = Context.Request.GetBufferType0x21();
 
-            byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, DataSize);
+            byte[] Data = Context.Memory.ReadBytes(DataPos, DataSize);
 
             Data = Parcel.GetParcelData(Data);