fix 7 correctness and cleanup issues
Blocking fixes: 1. Read<T> now returns default(T) on failed/partial read instead of crash (applies to single Read<T>, array Read<T>, and ReadBytes) 2. InProcessReader uses ReadProcessMemory via handle instead of unsafe Buffer.MemoryCopy — fails soft on bad address instead of AV'ing 3. GetRelative now returns absolute - ImageBase (inverse of GetAbsolute). Fix round-trip test to validate at arbitrary offsets, not just ImageBase 4. ReadString reads in 64-byte chunks with encoding-aware null-terminator pattern matching (handles UTF-16's 2-byte null, UTF-32's 4-byte null) Cleanup: 5. InProcessReader validates handle on open and uses RPM through it (handle is no longer unused) 6. Array marshal read: pin raw buffer once, PtrToStructure at offset 7. StructureToByteArray(Span) delegates to byte[] overload, no duplicate New tests: 4 invalid-address grace tests (returns default/empty/false). All 57 passing.
This commit is contained in:
@@ -7,6 +7,8 @@ namespace WhiteMagicTest;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for relative/absolute addressing in <see cref="MemoryBase"/>.
|
||||
/// GetAbsolute(relative) = ImageBase + relative.
|
||||
/// GetRelative(absolute) = absolute - ImageBase (inverse of GetAbsolute).
|
||||
/// </summary>
|
||||
public class AddressingTests
|
||||
{
|
||||
@@ -27,31 +29,45 @@ public class AddressingTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetRelative_computes_offset_from_image_base()
|
||||
public void GetRelative_returns_absolute_minus_image_base()
|
||||
{
|
||||
using var reader = OpenSelf();
|
||||
IntPtr imageBase = reader.ImageBase;
|
||||
IntPtr absolute = imageBase + 0x2000;
|
||||
IntPtr relative = reader.GetRelative(absolute);
|
||||
// GetRelative returns ImageBase - absolute (GreyMagic convention)
|
||||
Assert.Equal((IntPtr)((int)imageBase - (int)absolute), relative);
|
||||
Assert.Equal((IntPtr)((nint)absolute - (nint)imageBase), relative);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAbsolute_after_GetRelative_at_image_base_returns_to_base()
|
||||
public void GetAbsolute_and_GetRelative_are_inverses()
|
||||
{
|
||||
using var reader = OpenSelf();
|
||||
IntPtr atBase = reader.ImageBase;
|
||||
IntPtr relative = reader.GetRelative(atBase);
|
||||
IntPtr back = reader.GetAbsolute(relative);
|
||||
Assert.Equal(atBase, back);
|
||||
IntPtr offset = (IntPtr)0x3000;
|
||||
|
||||
// Round-trip: offset -> absolute -> back to offset
|
||||
IntPtr absolute = reader.GetAbsolute(offset);
|
||||
IntPtr back = reader.GetRelative(absolute);
|
||||
Assert.Equal(offset, back);
|
||||
|
||||
// Reverse round-trip: absolute -> offset -> back to absolute
|
||||
IntPtr relative = reader.GetRelative(absolute);
|
||||
IntPtr absoluteAgain = reader.GetAbsolute(relative);
|
||||
Assert.Equal(absolute, absoluteAgain);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetRelative_on_ImageBase_returns_zero()
|
||||
{
|
||||
using var reader = OpenSelf();
|
||||
IntPtr relative = reader.GetRelative(reader.ImageBase);
|
||||
Assert.Equal(IntPtr.Zero, relative);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Read_with_isRelative_true_uses_image_base()
|
||||
{
|
||||
using var reader = OpenSelf();
|
||||
// Read the first byte at ImageBase (should be MZ header: 0x4D = 'M')
|
||||
// DOS header 'MZ' at the image base
|
||||
byte firstByte = reader.Read<byte>(IntPtr.Zero, isRelative: true);
|
||||
Assert.Equal(0x4D, firstByte);
|
||||
}
|
||||
@@ -65,10 +81,9 @@ public class AddressingTests
|
||||
try
|
||||
{
|
||||
IntPtr absolute = pin.AddrOfPinnedObject();
|
||||
nint relative = (nint)absolute - (nint)reader.ImageBase;
|
||||
IntPtr relativePtr = (IntPtr)relative;
|
||||
IntPtr relative = reader.GetRelative(absolute);
|
||||
|
||||
Assert.True(reader.Write(relativePtr, 42, isRelative: true));
|
||||
Assert.True(reader.Write(relative, 42, isRelative: true));
|
||||
Assert.Equal(42, reader.Read<int>(absolute));
|
||||
}
|
||||
finally
|
||||
@@ -81,7 +96,6 @@ public class AddressingTests
|
||||
public void ReadBytes_with_isRelative_true_resolves_correctly()
|
||||
{
|
||||
using var reader = OpenSelf();
|
||||
// DOS header 'MZ' at the image base
|
||||
byte[] data = reader.ReadBytes(IntPtr.Zero, 2, isRelative: true);
|
||||
Assert.Equal(0x4D, data[0]);
|
||||
Assert.Equal(0x5A, data[1]);
|
||||
|
||||
Reference in New Issue
Block a user