Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/CoreFx.Private.TestUtilities/ref/Configurations.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<Project>
<PropertyGroup>
<BuildConfigurations>
netcoreapp;
netstandard;
uap;
</BuildConfigurations>
</PropertyGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{E2E59C98-998F-9965-991D-99411166AF6F}</ProjectGuid>
<ShouldWriteSigningRequired>false</ShouldWriteSigningRequired>
<AllowReferenceFromRuntime>true</AllowReferenceFromRuntime>
<RuntimeProjectFile>$(RepoRoot)\external\test-runtime\XUnit.Runtime.depproj</RuntimeProjectFile>
<Configurations>netstandard-Debug;netstandard-Release</Configurations>
<Configurations>netcoreapp-Debug;netcoreapp-Release;netstandard-Debug;netstandard-Release;uap-Debug;uap-Release</Configurations>
</PropertyGroup>
<ItemGroup>
<Compile Include="CoreFx.Private.TestUtilities.cs" />
<ReferenceFromRuntime Include="xunit.core" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp' OR '$(TargetGroup)' == 'uap'">
<Compile Include="CoreFx.Private.TestUtilities.netcoreapp.cs" />
<ProjectReference Include="..\..\System.Collections\ref\System.Collections.csproj" />
<ProjectReference Include="..\..\System.Diagnostics.Process\ref\System.Diagnostics.Process.csproj" />
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Runtime.InteropServices\ref\System.Runtime.InteropServices.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ------------------------------------------------------------------------------
// Changes to this file must follow the http://aka.ms/api-review process.
// ------------------------------------------------------------------------------

namespace System.Buffers
{
public static partial class BoundedMemory
{
public static System.Buffers.BoundedMemory<T> Allocate<T>(int elementCount, System.Buffers.PoisonPagePlacement placement = System.Buffers.PoisonPagePlacement.After) where T : unmanaged { throw null; }
public static System.Buffers.BoundedMemory<T> AllocateFromExistingData<T>(System.ReadOnlySpan<T> data, System.Buffers.PoisonPagePlacement placement = System.Buffers.PoisonPagePlacement.After) where T : unmanaged { throw null; }
public static System.Buffers.BoundedMemory<T> AllocateFromExistingData<T>(T[] data, System.Buffers.PoisonPagePlacement placement = System.Buffers.PoisonPagePlacement.After) where T : unmanaged { throw null; }
}
public abstract partial class BoundedMemory<T> : IDisposable where T : unmanaged
{
public abstract bool IsReadonly { get; }
public abstract System.Memory<T> Memory { get; }
public abstract System.Span<T> Span { get; }
public abstract void Dispose();
public abstract void MakeReadonly();
public abstract void MakeWriteable();
}
public enum PoisonPagePlacement
{
After = 0,
Before = 1,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetGroup)' == 'netstandard'">Test Utilities are not supported on this platform</GeneratePlatformNotSupportedAssemblyMessage>
<Configurations>netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;netcoreapp2.0-Unix-Debug;netcoreapp2.0-Unix-Release;netcoreapp2.0-Windows_NT-Debug;netcoreapp2.0-Windows_NT-Release;netcoreappaot-Windows_NT-Debug;netcoreappaot-Windows_NT-Release;netfx-Windows_NT-Debug;netfx-Windows_NT-Release;netstandard-Debug;netstandard-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release;uapaot-Windows_NT-Debug;uapaot-Windows_NT-Release</Configurations>
</PropertyGroup>
<ItemGroup>
<Compile Include="System\Buffers\BoundedMemory.cs" />
<Compile Include="System\Buffers\BoundedMemory.Creation.cs" />
<Compile Include="System\Buffers\BoundedMemory.Unix.cs" Condition="'$(TargetsWindows)' != 'true'" />
<Compile Include="System\Buffers\BoundedMemory.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
<Compile Include="System\Buffers\PoisonPagePlacement.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'netstandard'">
<Compile Include="System\AdminHelpers.cs" />
<Compile Include="System\IO\FileCleanupTestBase.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.InteropServices;

namespace System.Buffers
{
/// <summary>
/// Contains factory methods to create <see cref="BoundedMemory{T}"/> instances.
/// </summary>
public static partial class BoundedMemory
{
/// <summary>
/// Allocates a new <see cref="BoundedMemory{T}"/> region which is immediately preceded by
/// or immediately followed by a poison (MEM_NOACCESS) page. If <paramref name="placement"/>
/// is <see cref="PoisonPagePlacement.Before"/>, then attempting to read the memory
/// immediately before the returned <see cref="BoundedMemory{T}"/> will result in an AV.
/// If <paramref name="placement"/> is <see cref="PoisonPagePlacement.After"/>, then
/// attempting to read the memory immediately after the returned <see cref="BoundedMemory{T}"/>
/// will result in AV.
/// </summary>
/// <remarks>
/// The newly-allocated memory will be populated with random data.
/// </remarks>
public static BoundedMemory<T> Allocate<T>(int elementCount, PoisonPagePlacement placement = PoisonPagePlacement.After) where T : unmanaged
{
if (elementCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(elementCount));
}
if (placement != PoisonPagePlacement.Before && placement != PoisonPagePlacement.After)
{
throw new ArgumentOutOfRangeException(nameof(placement));
}

var retVal = AllocateWithoutDataPopulation<T>(elementCount, placement);
FillRandom(MemoryMarshal.AsBytes(retVal.Span));
return retVal;
}

/// <summary>
/// Similar to <see cref="Allocate(int, PoisonPagePlacement)"/>, but populates the allocated
/// native memory block from existing data rather than using random data.
/// </summary>
public static BoundedMemory<T> AllocateFromExistingData<T>(ReadOnlySpan<T> data, PoisonPagePlacement placement = PoisonPagePlacement.After) where T : unmanaged
{
if (placement != PoisonPagePlacement.Before && placement != PoisonPagePlacement.After)
{
throw new ArgumentOutOfRangeException(nameof(placement));
}

var retVal = AllocateWithoutDataPopulation<T>(data.Length, placement);
data.CopyTo(retVal.Span);
return retVal;
}

/// <summary>
/// Similar to <see cref="Allocate(int, PoisonPagePlacement)"/>, but populates the allocated
/// native memory block from existing data rather than using random data.
/// </summary>
public static BoundedMemory<T> AllocateFromExistingData<T>(T[] data, PoisonPagePlacement placement = PoisonPagePlacement.After) where T : unmanaged
{
return AllocateFromExistingData(new ReadOnlySpan<T>(data), placement);
}

private static void FillRandom(Span<byte> buffer)
{
// Loop over a Random instance manually since Random.NextBytes(Span<byte>) doesn't
// exist on all platforms we target.

Random random = new Random(); // doesn't need to be cryptographically strong

for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)random.Next();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Buffers
{
public static partial class BoundedMemory
{
private static UnixImplementation<T> AllocateWithoutDataPopulation<T>(int elementCount, PoisonPagePlacement placement) where T : unmanaged
{
// On non-Windows platforms, we don't yet have support for changing the permissions of individual pages.

return new UnixImplementation<T>(elementCount);
}

private sealed class UnixImplementation<T> : BoundedMemory<T> where T : unmanaged
{
private readonly T[] _buffer;

public UnixImplementation(int elementCount)
{
_buffer = new T[elementCount];
}

public override bool IsReadonly => false;

public override Memory<T> Memory => _buffer;

public override Span<T> Span => _buffer;

public override void Dispose()
{
// no-op
}

public override void MakeReadonly()
{
// no-op
}

public override void MakeWriteable()
{
// no-op
}
}
}
}
Loading