Browse Source

MEMORY_SENTINEL

af/UniformUnmanagedMemoryPoolMemoryAllocator-02-MemoryGuards
Anton Firszov 5 years ago
parent
commit
a329a3a8a2
  1. 1
      src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.Buffer{T}.cs
  2. 6
      src/ImageSharp/Memory/Allocators/Internals/UnmanagedBuffer{T}.cs
  3. 30
      src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs

1
src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.Buffer{T}.cs

@ -26,6 +26,7 @@ namespace SixLabors.ImageSharp.Memory.Internals
return; return;
} }
this.VerifyMemorySentinel();
this.pool.Return(this.BufferHandle); this.pool.Return(this.BufferHandle);
this.pool = null; this.pool = null;
this.BufferHandle = null; this.BufferHandle = null;

6
src/ImageSharp/Memory/Allocators/Internals/UnmanagedBuffer{T}.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -61,10 +62,15 @@ namespace SixLabors.ImageSharp.Memory.Internals
return; return;
} }
this.VerifyMemorySentinel();
if (disposing) if (disposing)
{ {
this.BufferHandle.Dispose(); this.BufferHandle.Dispose();
} }
} }
[Conditional("MEMORY_SENTINEL")]
protected void VerifyMemorySentinel() => this.BufferHandle.VerifyMemorySentinel(this.lengthInElements * Unsafe.SizeOf<T>());
} }
} }

30
src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using Microsoft.Win32.SafeHandles; using Microsoft.Win32.SafeHandles;
@ -24,6 +25,12 @@ namespace SixLabors.ImageSharp.Memory.Internals
// A Monitor to wait/signal when we are low on memory. // A Monitor to wait/signal when we are low on memory.
private static object lowMemoryMonitor; private static object lowMemoryMonitor;
#if MEMORY_SENTINEL
private const int MemorySentinelPadding = 16;
#else
private const int MemorySentinelPadding = 0;
#endif
private UnmanagedMemoryHandle(IntPtr handle, int lengthInBytes) private UnmanagedMemoryHandle(IntPtr handle, int lengthInBytes)
: base(handle, true) : base(handle, true)
{ {
@ -77,10 +84,31 @@ namespace SixLabors.ImageSharp.Memory.Internals
internal static UnmanagedMemoryHandle Allocate(int lengthInBytes) internal static UnmanagedMemoryHandle Allocate(int lengthInBytes)
{ {
IntPtr handle = AllocateHandle(lengthInBytes); IntPtr handle = AllocateHandle(lengthInBytes + MemorySentinelPadding);
#if MEMORY_SENTINEL
unsafe
{
new Span<byte>((void*)handle, lengthInBytes + MemorySentinelPadding).Fill(42);
}
#endif
return new UnmanagedMemoryHandle(handle, lengthInBytes); return new UnmanagedMemoryHandle(handle, lengthInBytes);
} }
[Conditional("MEMORY_SENTINEL")]
internal unsafe void VerifyMemorySentinel(int actualLengthInBytes)
{
Span<byte> remainder =
new Span<byte>((void*)this.handle, this.lengthInBytes + MemorySentinelPadding)
.Slice(actualLengthInBytes);
for (int i = 0; i < remainder.Length; i++)
{
if (remainder[i] != 42)
{
throw new InvalidMemoryOperationException("Memory corruption detected!");
}
}
}
private static IntPtr AllocateHandle(int lengthInBytes) private static IntPtr AllocateHandle(int lengthInBytes)
{ {
int counter = 0; int counter = 0;

Loading…
Cancel
Save