Fix bounds, memory protection, and completion race in core helpers
- AllocatedMemory.Read<T>/Write<T>/ReadBytes/WriteBytes now validate that the requested byte range stays within the allocated block before calling into the memory accessor. - Patch.Apply/Remove temporarily changes the target page to read-write and restores the original protection, mirroring the Detour behavior. - MainThreadPump.WorkItem uses TrySetResult/TrySetException and swallows the InvalidOperationException raised when a completion source is already completed, preventing Dispose from failing during concurrent pump drainage. Regression tests added for all three fixes. Tests: 206 passing, 4 skipped.
This commit is contained in:
@@ -83,7 +83,7 @@ public sealed class MainThreadPump : IDisposable
|
||||
throw new InvalidOperationException("The main-thread pump is not installed. Call Install() first.");
|
||||
|
||||
object? Box() => work()!;
|
||||
_queue.Enqueue(new WorkItem(Box, r => tcs.SetResult((TResult)r!), ex => tcs.SetException(ex)));
|
||||
_queue.Enqueue(new WorkItem(Box, r => tcs.TrySetResult((TResult)r!), ex => tcs.TrySetException(ex)));
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
@@ -158,20 +158,34 @@ public sealed class MainThreadPump : IDisposable
|
||||
public WorkItem(Func<object?> work, TaskCompletionSource<object?> tcs)
|
||||
{
|
||||
Work = work;
|
||||
_setResult = r => tcs.SetResult(r);
|
||||
_setException = ex => tcs.SetException(ex);
|
||||
_setResult = r => tcs.TrySetResult(r);
|
||||
_setException = ex => tcs.TrySetException(ex);
|
||||
}
|
||||
|
||||
public Func<object?> Work { get; }
|
||||
|
||||
public void SetResult(object? result)
|
||||
{
|
||||
_setResult?.Invoke(result);
|
||||
try
|
||||
{
|
||||
_setResult?.Invoke(result);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// Already completed, e.g. concurrent Dispose/PumpHook race.
|
||||
}
|
||||
}
|
||||
|
||||
public void SetException(Exception exception)
|
||||
{
|
||||
_setException?.Invoke(exception);
|
||||
try
|
||||
{
|
||||
_setException?.Invoke(exception);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// Already completed, e.g. concurrent Dispose/PumpHook race.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user