Fix crashing due to bug in BufferWriter.ToByteArray()

Renamed the serialisers and added CustomEvents to unit test to be more future-proof
This commit is contained in:
Sardelka9515
2023-02-03 13:37:20 +08:00
parent b4f86719ce
commit 718814c491
5 changed files with 48 additions and 30 deletions

View File

@ -5,7 +5,7 @@ using GTA.Math;
namespace RageCoop.Core
{
public unsafe abstract class BufferBase
public unsafe abstract class Buffer
{
/// <summary>
/// Size of this buffer in memory
@ -41,9 +41,9 @@ namespace RageCoop.Core
}
}
public unsafe sealed class WriteBuffer : BufferBase
public unsafe sealed class BufferWriter : Buffer
{
public WriteBuffer(int size)
public BufferWriter(int size)
{
Resize(size);
}
@ -59,7 +59,7 @@ namespace RageCoop.Core
var newAddr = (byte*)Marshal.AllocHGlobal(size);
if (Address != null)
{
Buffer.MemoryCopy(Address, newAddr, size, Size);
System.Buffer.MemoryCopy(Address, newAddr, size, Size);
Marshal.FreeHGlobal((IntPtr)Address);
}
Size = size;
@ -138,14 +138,14 @@ namespace RageCoop.Core
var len = source.Length;
fixed (T* pSource = source)
{
Buffer.MemoryCopy(pSource, Alloc(sizeof(T) * len), len, len);
System.Buffer.MemoryCopy(pSource, Alloc(sizeof(T) * len), len, len);
}
}
public void Write<T>(Span<T> source) where T : unmanaged => Write((ReadOnlySpan<T>)source);
/// <summary>
/// Write an array, prefix the data with its length so it can latter be read using <see cref="ReadBuffer.ReadArray{T}"/>
/// Write an array, prefix the data with its length so it can latter be read using <see cref="BufferReader.ReadArray{T}"/>
/// </summary>
public void WriteArray<T>(T[] values) where T : unmanaged
{
@ -153,7 +153,7 @@ namespace RageCoop.Core
WriteVal(len);
fixed (T* pFrom = values)
{
Buffer.MemoryCopy(pFrom, Alloc(sizeof(T) * len), len, len);
System.Buffer.MemoryCopy(pFrom, Alloc(sizeof(T) * len), len, len);
}
}
@ -171,7 +171,7 @@ namespace RageCoop.Core
var result = new byte[cbSize];
fixed (byte* pResult = result)
{
Buffer.MemoryCopy(Address, pResult, Size, Size);
System.Buffer.MemoryCopy(Address, pResult, cbSize, cbSize);
}
return result;
}
@ -182,16 +182,16 @@ namespace RageCoop.Core
public void Free() => Marshal.FreeHGlobal((IntPtr)Address);
}
public unsafe sealed class ReadBuffer : BufferBase
public unsafe sealed class BufferReader : Buffer
{
/// <summary>
/// Initialize an empty instance, needs to call <see cref="Initialise(byte*, int)"/> before reading data
/// </summary>
public ReadBuffer()
public BufferReader()
{
}
public ReadBuffer(byte* address, int size) => Initialise(address, size);
public BufferReader(byte* address, int size) => Initialise(address, size);
public void Initialise(byte* address, int size)
{
@ -269,12 +269,12 @@ namespace RageCoop.Core
var len = destination.Length;
fixed (T* pTo = destination)
{
Buffer.MemoryCopy(Alloc(len * sizeof(T)), pTo, len, len);
System.Buffer.MemoryCopy(Alloc(len * sizeof(T)), pTo, len, len);
}
}
/// <summary>
/// Reads an array previously written using <see cref="WriteBuffer.WriteArray{T}(T[])"/>
/// Reads an array previously written using <see cref="BufferWriter.WriteArray{T}(T[])"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
@ -285,7 +285,7 @@ namespace RageCoop.Core
var result = new T[len];
fixed (T* pTo = result)
{
Buffer.MemoryCopy(from, pTo, len, len);
System.Buffer.MemoryCopy(from, pTo, len, len);
}
return result;
}

View File

@ -27,11 +27,11 @@ namespace RageCoop.Core
m.Write(Hash);
if (Args != null)
{
lock (WriteBufferShared)
lock (SharedWriter)
{
WriteBufferShared.Reset();
CustomEvents.WriteObjects(WriteBufferShared, Args);
Payload = WriteBufferShared.ToByteArray(WriteBufferShared.Position);
SharedWriter.Reset();
CustomEvents.WriteObjects(SharedWriter, Args);
Payload = SharedWriter.ToByteArray(SharedWriter.Position);
}
}
m.Write(Payload);
@ -44,10 +44,10 @@ namespace RageCoop.Core
Payload = m.ReadBytes(m.LengthBytes - m.PositionInBytes);
fixed (byte* p = Payload)
{
lock (ReadBufferShared)
lock (SharedReader)
{
ReadBufferShared.Initialise(p,Payload.Length);
Args = CustomEvents.ReadObjects(ReadBufferShared);
SharedReader.Initialise(p, Payload.Length);
Args = CustomEvents.ReadObjects(SharedReader);
}
}
}

View File

@ -152,8 +152,8 @@ namespace RageCoop.Core
internal abstract class Packet : IPacket
{
public static WriteBuffer WriteBufferShared = new(1024);
public static ReadBuffer ReadBufferShared = new();
public static BufferWriter SharedWriter = new(1024);
public static BufferReader SharedReader = new();
public abstract PacketType Type { get; }

View File

@ -143,10 +143,10 @@ namespace RageCoop.Core.Scripting
#endregion
public static void WriteObjects(WriteBuffer b, params object[] objs)
public static void WriteObjects(BufferWriter b, params object[] objs)
{
b.WriteVal(objs.Length);
foreach(var obj in objs)
foreach (var obj in objs)
{
switch (obj)
{
@ -219,7 +219,7 @@ namespace RageCoop.Core.Scripting
}
}
}
public static object[] ReadObjects(ReadBuffer r)
public static object[] ReadObjects(BufferReader r)
{
var Args = new object[r.ReadVal<int>()];
for (var i = 0; i < Args.Length; i++)
@ -280,7 +280,7 @@ namespace RageCoop.Core.Scripting
case T_ID_PED:
case T_ID_PROP:
case T_ID_VEH:
Args[i] = IdToHandle(type,r.ReadVal<int>());
Args[i] = IdToHandle(type, r.ReadVal<int>());
break;
default:
throw new InvalidOperationException($"Unexpected type: {type}");
@ -290,6 +290,6 @@ namespace RageCoop.Core.Scripting
}
[LibraryImport("RageCoop.Client.dll")]
public static partial int IdToHandle(byte type,int id);
public static partial int IdToHandle(byte type, int id);
}
}

View File

@ -1,5 +1,6 @@
using GTA.Math;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using System.Security.Cryptography;
namespace UnitTest
@ -28,7 +29,7 @@ namespace UnitTest
{
TestElement[] test = new TestElement[1024];
Console.WriteLine("Testing buffers");
var buf = new WriteBuffer(1024);
var buf = new BufferWriter(1024);
for (int i = 0; i < 1024; i++)
{
var e = test[i] = new TestElement(i);
@ -42,7 +43,7 @@ namespace UnitTest
Console.WriteLine($"Current position: {buf.Position}");
Console.WriteLine("Validating data");
var reader = new ReadBuffer(buf.Address, buf.Size);
var reader = new BufferReader(buf.Address, buf.Size);
for (int i = 0; i < 1024; i++)
{
var e = test[i];
@ -69,6 +70,23 @@ namespace UnitTest
}
Console.WriteLine("Buffers OK");
Console.WriteLine("Testing CustomEvents");
var objs = new object[] { (byte)236, (short)82, (ushort)322,
"test", 123, 123U, 456UL, 345L, 5F, new Vector2(15, 54), new Vector3(22, 45, 25), new Quaternion(2, 3, 222, 5) };
buf.Reset();
CustomEvents.WriteObjects(buf, objs);
var payload = buf.ToByteArray(buf.Position);
fixed(byte* p = payload)
{
reader.Initialise(p, payload.Length);
}
if (!CustomEvents.ReadObjects(reader).SequenceEqual(objs))
throw new Exception("CustomEvents fail");
Console.WriteLine("CustomEvents OK");
}
}
}