Removal of unsafe and check if PTR is correctly aligning, checking in virtual query instead of memory
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||||
using LightlessSync.API.Data.Enum;
|
|
||||||
using LightlessSync.FileCache;
|
using LightlessSync.FileCache;
|
||||||
using LightlessSync.Interop.Ipc;
|
using LightlessSync.Interop.Ipc;
|
||||||
using LightlessSync.LightlessConfiguration;
|
using LightlessSync.LightlessConfiguration;
|
||||||
@@ -14,6 +13,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using ObjectKind = LightlessSync.API.Data.Enum.ObjectKind;
|
||||||
|
|
||||||
namespace LightlessSync.PlayerData.Factories;
|
namespace LightlessSync.PlayerData.Factories;
|
||||||
|
|
||||||
@@ -119,39 +119,48 @@ public class PlayerDataFactory
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly int _drawObjectOffset =
|
||||||
|
(int)Marshal.OffsetOf<GameObject>(nameof(GameObject.DrawObject));
|
||||||
|
|
||||||
private async Task<bool> CheckForNullDrawObject(IntPtr playerPointer)
|
private async Task<bool> CheckForNullDrawObject(IntPtr playerPointer)
|
||||||
=> await _dalamudUtil.RunOnFrameworkThread(() => CheckForNullDrawObjectUnsafe(playerPointer)).ConfigureAwait(false);
|
=> await _dalamudUtil.RunOnFrameworkThread(() =>
|
||||||
|
{
|
||||||
|
nint basePtr = playerPointer;
|
||||||
|
|
||||||
private unsafe static bool CheckForNullDrawObjectUnsafe(IntPtr playerPointer)
|
if (!LooksLikeUserPtr(basePtr))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
nint drawObjAddr = basePtr + _drawObjectOffset;
|
||||||
|
|
||||||
|
if (!TryReadIntPtr(drawObjAddr, out var drawObj))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return drawObj == 0;
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
private static bool LooksLikeUserPtr(nint p)
|
||||||
{
|
{
|
||||||
if (playerPointer == IntPtr.Zero)
|
if (p == 0) return false;
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!IsPointerValid(playerPointer))
|
ulong u = (ulong)p;
|
||||||
return true;
|
|
||||||
|
|
||||||
var character = (Character*)playerPointer;
|
if (u < 0x0000_0001_0000UL) return false;
|
||||||
if (character == null)
|
if (u > 0x0000_7FFF_FFFF_FFFFUL) return false;
|
||||||
return true;
|
if ((u & 0x7UL) != 0) return false;
|
||||||
|
|
||||||
var gameObject = &character->GameObject;
|
return true;
|
||||||
if (gameObject == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!IsPointerValid((IntPtr)gameObject))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return gameObject->DrawObject == null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsPointerValid(IntPtr ptr)
|
private static bool TryReadIntPtr(nint addr, out nint value)
|
||||||
{
|
{
|
||||||
if (ptr == IntPtr.Zero)
|
value = 0;
|
||||||
|
|
||||||
|
if (!VirtualReadable(addr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_ = Marshal.ReadByte(ptr);
|
value = Marshal.ReadIntPtr(addr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -160,6 +169,38 @@ public class PlayerDataFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool VirtualReadable(nint addr)
|
||||||
|
{
|
||||||
|
if (VirtualQuery(addr, out var mbi, (nuint)Marshal.SizeOf<MEMORY_BASIC_INFORMATION>()) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const uint MEM_COMMIT = 0x1000;
|
||||||
|
const uint PAGE_NOACCESS = 0x01;
|
||||||
|
const uint PAGE_GUARD = 0x100;
|
||||||
|
|
||||||
|
if (mbi.State != MEM_COMMIT) return false;
|
||||||
|
if ((mbi.Protect & PAGE_GUARD) != 0) return false;
|
||||||
|
if (mbi.Protect == PAGE_NOACCESS) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
private static extern nuint VirtualQuery(nint lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, nuint dwLength);
|
||||||
|
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct MEMORY_BASIC_INFORMATION
|
||||||
|
{
|
||||||
|
public nint BaseAddress;
|
||||||
|
public nint AllocationBase;
|
||||||
|
public uint AllocationProtect;
|
||||||
|
public nuint RegionSize;
|
||||||
|
public uint State;
|
||||||
|
public uint Protect;
|
||||||
|
public uint Type;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsCacheFresh(CacheEntry entry)
|
private static bool IsCacheFresh(CacheEntry entry)
|
||||||
=> (DateTime.UtcNow - entry.CreatedUtc) <= _characterCacheTtl;
|
=> (DateTime.UtcNow - entry.CreatedUtc) <= _characterCacheTtl;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user