Fix fallback read too short for sparse prologues in redirection helper
Replace the two-attempt read with a single read sized to the smaller of: - detourLength + 16 (the decoder's preferred window), and - bytes remaining in the current page (so ReadProcessMemory does not fail whole read). Reading only detourLength bytes could leave the instruction analyzer without enough bytes to resolve a multi-byte instruction that crosses the splice point on sparse prologues. Reading up to the page boundary gives the largest safe window. Tests: 199 passing, 4 integration/interactive skipped.
This commit is contained in:
@@ -66,18 +66,21 @@ public sealed class Detour : IDisposable
|
||||
int pointerSize = _memory.Is64Bit ? 8 : 4;
|
||||
int detourLength = pointerSize == 8 ? 14 : 5;
|
||||
|
||||
// Try to read detourLength + 16 bytes for the prologue decoder.
|
||||
// If the target is near a page boundary, this might fail, so fall back to the minimum.
|
||||
byte[] prologue = _memory.ReadBytes(Target, detourLength + 16);
|
||||
// The prologue decoder may need to see bytes past the minimum detour length
|
||||
// to identify the whole instruction that crosses the splice point. Prefer a
|
||||
// generous read, but if the target sits near an unmapped page boundary, read
|
||||
// only up to that boundary so ReadProcessMemory does not fail entirely.
|
||||
int preferredBuffer = detourLength + 16;
|
||||
int pageSize = Environment.SystemPageSize;
|
||||
int pageOffset = (int)(Target.ToInt64() & (pageSize - 1));
|
||||
int bytesToPageBoundary = pageSize - pageOffset;
|
||||
int readSize = Math.Min(preferredBuffer, bytesToPageBoundary);
|
||||
|
||||
byte[] prologue = _memory.ReadBytes(Target, readSize);
|
||||
if (prologue.Length < detourLength)
|
||||
{
|
||||
// Second attempt: read only the minimum required bytes
|
||||
prologue = _memory.ReadBytes(Target, detourLength);
|
||||
if (prologue.Length < detourLength)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Could not read enough bytes from the target function to install a detour.");
|
||||
}
|
||||
throw new InvalidOperationException(
|
||||
"Could not read enough bytes from the target function to install a detour.");
|
||||
}
|
||||
|
||||
int preserveLength = PrologueDecoder.GetWholeInstructionLength(prologue, detourLength, _memory.Is64Bit);
|
||||
|
||||
Reference in New Issue
Block a user