diff --git a/src/Castle.Facilities.NHibernateIntegration/Components/Web/SessionWebModule.cs b/src/Castle.Facilities.NHibernateIntegration/Components/Web/SessionWebModule.cs index 9b5a87222..1db1855ff 100644 --- a/src/Castle.Facilities.NHibernateIntegration/Components/Web/SessionWebModule.cs +++ b/src/Castle.Facilities.NHibernateIntegration/Components/Web/SessionWebModule.cs @@ -87,10 +87,7 @@ private void OnEndRequest(object sender, EventArgs e) { var session = (ISession) HttpContext.Current.Items[SessionKey]; - if (session != null) - { - session.Dispose(); - } + session?.Dispose(); } private static IWindsorContainer ObtainContainer() diff --git a/src/Castle.Facilities.NHibernateIntegration/Persisters/ObjectPersisters.cs b/src/Castle.Facilities.NHibernateIntegration/Persisters/ObjectPersisters.cs index a742cfacc..26deaf356 100644 --- a/src/Castle.Facilities.NHibernateIntegration/Persisters/ObjectPersisters.cs +++ b/src/Castle.Facilities.NHibernateIntegration/Persisters/ObjectPersisters.cs @@ -28,28 +28,24 @@ public class ObjectPersister : IObjectPersister public T Read(string filePath, FileMode mode = FileMode.OpenOrCreate) { using var stream = new FileStream(filePath, mode); - using var allocation = ArrayPool.Shared.Allocate((int) stream.Length); - var bytes = allocation.Values; -#if NETFRAMEWORK - stream.Read(bytes, 0, bytes.Length); - var @object = (T) SerializationHelper.Deserialize(bytes); + using var allocation = ArrayPool.Shared.AllocateByte((int) stream.Length, true); + var buffer = allocation.Buffer; +#if NET + stream.Read(buffer.AsSpan()); #else - var bytesAsSpan = bytes.AsSpan(); - stream.Read(bytesAsSpan); - var @object = (T) SerializationHelper.Deserialize(bytesAsSpan.ToArray()); + stream.Read(buffer, 0, buffer.Length); #endif - return @object; + return (T) SerializationHelper.Deserialize(buffer); } public void Write(T @object, string filePath, FileMode mode = FileMode.OpenOrCreate) { using var stream = new FileStream(filePath, mode); - var bytes = SerializationHelper.Serialize(@object); -#if NETFRAMEWORK - stream.Write(bytes, 0, bytes.Length); + var buffer = SerializationHelper.Serialize(@object); +#if NET + stream.Write(buffer.AsSpan()); #else - var bytesAsSpan = bytes.AsSpan(); - stream.Write(bytesAsSpan); + stream.Write(buffer, 0, buffer.Length); #endif } } diff --git a/src/Castle.Facilities.NHibernateIntegration/SessionStores/CallContextSessionStore.cs b/src/Castle.Facilities.NHibernateIntegration/SessionStores/CallContextSessionStore.cs index 0f2c3896a..bd75c8d04 100644 --- a/src/Castle.Facilities.NHibernateIntegration/SessionStores/CallContextSessionStore.cs +++ b/src/Castle.Facilities.NHibernateIntegration/SessionStores/CallContextSessionStore.cs @@ -16,9 +16,10 @@ namespace Castle.Facilities.NHibernateIntegration.SessionStores { +#if NET using System; +#endif using System.Collections.Generic; - #if NETFRAMEWORK using System.Runtime.Remoting.Messaging; @@ -27,6 +28,7 @@ namespace Castle.Facilities.NHibernateIntegration.SessionStores /// which relies on . /// #else + /// /// An implementation of /// which relies on .NET Framework CallContext. diff --git a/src/Castle.Facilities.NHibernateIntegration/SessionStores/LogicalCallContextSessionStore.cs b/src/Castle.Facilities.NHibernateIntegration/SessionStores/LogicalCallContextSessionStore.cs index cedc51877..b20a7fdc1 100644 --- a/src/Castle.Facilities.NHibernateIntegration/SessionStores/LogicalCallContextSessionStore.cs +++ b/src/Castle.Facilities.NHibernateIntegration/SessionStores/LogicalCallContextSessionStore.cs @@ -16,19 +16,19 @@ namespace Castle.Facilities.NHibernateIntegration.SessionStores { +#if NET using System; +#endif using System.Collections.Generic; - - #if NETFRAMEWORK using System.Runtime.Remoting.Messaging; -#endif -#if NETFRAMEWORK + /// /// An implementation of /// which relies on logical . /// #else + /// /// An implementation of /// which relies on .NET Framework logical CallContext. @@ -37,7 +37,6 @@ namespace Castle.Facilities.NHibernateIntegration.SessionStores /// This is not supported anymore in .NET. /// #endif - public class LogicalCallContextSessionStore : AbstractDictionaryStackSessionStore { protected override IDictionary> GetSessionDictionary() diff --git a/src/Castle.Facilities.NHibernateIntegration/SessionStores/WebSessionStore.cs b/src/Castle.Facilities.NHibernateIntegration/SessionStores/WebSessionStore.cs index 8a8716443..ea9744edc 100644 --- a/src/Castle.Facilities.NHibernateIntegration/SessionStores/WebSessionStore.cs +++ b/src/Castle.Facilities.NHibernateIntegration/SessionStores/WebSessionStore.cs @@ -23,8 +23,8 @@ namespace Castle.Facilities.NHibernateIntegration.SessionStores #endif using MicroKernel.Facilities; - #if NET + using Microsoft.AspNetCore.Http; #endif diff --git a/src/Castle.Facilities.NHibernateIntegration/Util/ArrayPoolExtensions.cs b/src/Castle.Facilities.NHibernateIntegration/Util/ArrayPoolExtensions.cs index 2b8a7ff80..81dfaa026 100644 --- a/src/Castle.Facilities.NHibernateIntegration/Util/ArrayPoolExtensions.cs +++ b/src/Castle.Facilities.NHibernateIntegration/Util/ArrayPoolExtensions.cs @@ -2,31 +2,86 @@ namespace Castle.Facilities.NHibernateIntegration.Util { using System; using System.Buffers; +#if NET + using System.Security.Cryptography; +#endif public static class ArrayPoolExtensions { - public static ArrayPoolAllocation Allocate(this ArrayPool pool, int minimumSize) + public static ArrayPoolAllocation Allocate(this ArrayPool pool, + int minimumLength, + bool clearBufferContents = false) { - return new ArrayPoolAllocation(pool, minimumSize); + return new ArrayPoolAllocation(pool, minimumLength, clearBufferContents); + } + + public static ArrayPoolByteAllocation AllocateByte(this ArrayPool pool, + int minimumLength, + bool clearBufferContents = false) + { + return new ArrayPoolByteAllocation(pool, minimumLength, clearBufferContents); } } public readonly struct ArrayPoolAllocation : IDisposable { private readonly ArrayPool _pool; + private readonly bool _clearBufferContents; + + internal ArrayPoolAllocation(ArrayPool pool, + int minimumLength, + bool clearBufferContents) + { + _pool = pool ?? throw new ArgumentNullException(nameof(pool)); + _clearBufferContents = clearBufferContents; + + Buffer = _pool.Rent(minimumLength); + } + + public T[] Buffer { get; } - internal ArrayPoolAllocation(ArrayPool pool, int minimumSize) + public void Dispose() + { + if (_clearBufferContents) + { + // https://github.com/dotnet/runtime/discussions/48697 + Buffer.AsSpan(0, Buffer.Length).Clear(); + } + + _pool.Return(Buffer); + } + } + + public readonly struct ArrayPoolByteAllocation : IDisposable + { + private readonly ArrayPool _pool; + private readonly bool _clearBufferContents; + + internal ArrayPoolByteAllocation(ArrayPool pool, + int minimumLength, + bool clearBufferContents) { _pool = pool ?? throw new ArgumentNullException(nameof(pool)); + _clearBufferContents = clearBufferContents; - Values = _pool.Rent(minimumSize); + Buffer = _pool.Rent(minimumLength); } - public T[] Values { get; } + public byte[] Buffer { get; } public void Dispose() { - _pool.Return(Values); + if (_clearBufferContents) + { + // https://github.com/dotnet/runtime/discussions/48697 +#if NET + CryptographicOperations.ZeroMemory(Buffer.AsSpan(0, Buffer.Length)); +#else + Buffer.AsSpan(0, Buffer.Length).Clear(); +#endif + } + + _pool.Return(Buffer); } } }