Harden memory layer: fix char sizing, ref structs, count guards, ReadString advance
Second-review fixes, each covered by a regression test in MemoryHardeningTests: - MarshalCache: special-case char (Size=2; Marshal.SizeOf reports 1/ANSI but the blittable path reads a 2-byte UTF-16 unit). TypeRequiresMarshal now also trips on RuntimeHelpers.IsReferenceOrContainsReferences<T>() so reference-carrying structs route to the marshal path instead of throwing in MemoryMarshal.Read. Document that the MarshalAs scan is top-level only. - MemoryBase.Read<T>(count): reject negative count (ArgumentOutOfRangeException) and guard elementSize*count overflow. Same overflow guard on Write<T>(values). - MemoryBase.ReadString: advance by bytes actually read, not the requested amount, so a partial read no longer skips the unread tail of the window. - ExternalReader: default to a minimal access set (not AllAccess, which over-requests and fails on protected processes); wrap Process.MainModule in try/catch so a bitness-mismatched or protected target yields ImageBase=Zero instead of throwing. - NativeMethods: WaitForSingleObject and CreateRemoteThread's threadId are DWORD (uint), not int — the signatures no longer sign-flip. Deferred: hoisting the identical ExternalReader/InProcessReader byte-IO into MemoryBase (cosmetic; skipped to avoid colliding with concurrent Phase 3 edits). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -85,7 +85,7 @@ internal static partial class NativeMethods
|
||||
IntPtr startAddress,
|
||||
IntPtr parameter,
|
||||
ThreadCreationFlags creationFlags,
|
||||
out int threadId);
|
||||
out uint threadId);
|
||||
|
||||
/// <summary>Sets a 64-bit thread context (AMD64).</summary>
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
@@ -128,9 +128,10 @@ internal static partial class NativeMethods
|
||||
IntPtr hModule,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string lpProcName);
|
||||
|
||||
/// <summary>Waits until a thread exits and retrieves its exit code.</summary>
|
||||
/// <summary>Waits until an object is signaled or the timeout elapses. Returns a
|
||||
/// <c>WAIT_*</c> status (DWORD); <c>WAIT_FAILED</c> is <c>0xFFFFFFFF</c>.</summary>
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
internal static partial int WaitForSingleObject(
|
||||
internal static partial uint WaitForSingleObject(
|
||||
SafeMemoryHandle handle,
|
||||
uint milliseconds);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user