diff options
author | Ludovic Henry <luhenry@microsoft.com> | 2017-11-13 23:16:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-13 23:16:03 +0300 |
commit | 33eb71ae07d40eb968fe15c7eec5db3950c466b3 (patch) | |
tree | 83b4df7a62a0a09bd3f4c8b8105c8d7eb9cafb44 /mcs/class/System | |
parent | bf1b5dced0ffe257fc208e499f9c524afcc469b2 (diff) |
[System] Fix DeflateStream crash with high concurrency on Read/Write/Close (#5994)
Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=56727
Diffstat (limited to 'mcs/class/System')
-rw-r--r-- | mcs/class/System/System.IO.Compression/DeflateStream.cs | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/mcs/class/System/System.IO.Compression/DeflateStream.cs b/mcs/class/System/System.IO.Compression/DeflateStream.cs index 354a16e39e3..64f20595975 100644 --- a/mcs/class/System/System.IO.Compression/DeflateStream.cs +++ b/mcs/class/System/System.IO.Compression/DeflateStream.cs @@ -332,7 +332,7 @@ namespace System.IO.Compression UnmanagedReadOrWrite feeder; // This will be passed to unmanaged code and used there Stream base_stream; - IntPtr z_stream; + SafeDeflateStreamHandle z_stream; GCHandle data; bool disposed; byte [] io_buffer; @@ -347,7 +347,7 @@ namespace System.IO.Compression dsn.data = GCHandle.Alloc (dsn); dsn.feeder = mode == CompressionMode.Compress ? new UnmanagedReadOrWrite (UnmanagedWrite) : new UnmanagedReadOrWrite (UnmanagedRead); dsn.z_stream = CreateZStream (mode, gzip, dsn.feeder, GCHandle.ToIntPtr (dsn.data)); - if (dsn.z_stream == IntPtr.Zero) { + if (dsn.z_stream.IsInvalid) { dsn.Dispose (true); return null; } @@ -369,10 +369,7 @@ namespace System.IO.Compression io_buffer = null; - IntPtr zz = z_stream; - z_stream = IntPtr.Zero; - if (zz != IntPtr.Zero) - CloseZStream (zz); // This will Flush() the remaining output if any + z_stream.Dispose(); } if (data.IsAllocated) { @@ -498,21 +495,21 @@ namespace System.IO.Compression #if !ORBIS [DllImport (LIBNAME, CallingConvention=CallingConvention.Cdecl)] - static extern IntPtr CreateZStream (CompressionMode compress, bool gzip, UnmanagedReadOrWrite feeder, IntPtr data); + static extern SafeDeflateStreamHandle CreateZStream (CompressionMode compress, bool gzip, UnmanagedReadOrWrite feeder, IntPtr data); [DllImport (LIBNAME, CallingConvention=CallingConvention.Cdecl)] static extern int CloseZStream (IntPtr stream); [DllImport (LIBNAME, CallingConvention=CallingConvention.Cdecl)] - static extern int Flush (IntPtr stream); + static extern int Flush (SafeDeflateStreamHandle stream); [DllImport (LIBNAME, CallingConvention=CallingConvention.Cdecl)] - static extern int ReadZStream (IntPtr stream, IntPtr buffer, int length); + static extern int ReadZStream (SafeDeflateStreamHandle stream, IntPtr buffer, int length); [DllImport (LIBNAME, CallingConvention=CallingConvention.Cdecl)] - static extern int WriteZStream (IntPtr stream, IntPtr buffer, int length); + static extern int WriteZStream (SafeDeflateStreamHandle stream, IntPtr buffer, int length); #else - static IntPtr CreateZStream (CompressionMode compress, bool gzip, UnmanagedReadOrWrite feeder, IntPtr data) + static SafeDeflateStreamHandle CreateZStream (CompressionMode compress, bool gzip, UnmanagedReadOrWrite feeder, IntPtr data) { throw new PlatformNotSupportedException (); } @@ -522,22 +519,39 @@ namespace System.IO.Compression throw new PlatformNotSupportedException (); } - static int Flush (IntPtr stream) + static int Flush (SafeDeflateStreamHandle stream) { throw new PlatformNotSupportedException (); } - static int ReadZStream (IntPtr stream, IntPtr buffer, int length) + static int ReadZStream (SafeDeflateStreamHandle stream, IntPtr buffer, int length) { throw new PlatformNotSupportedException (); } - static int WriteZStream (IntPtr stream, IntPtr buffer, int length) + static int WriteZStream (SafeDeflateStreamHandle stream, IntPtr buffer, int length) { throw new PlatformNotSupportedException (); } #endif + sealed class SafeDeflateStreamHandle : SafeHandle + { + public override bool IsInvalid + { + get { return handle == IntPtr.Zero; } + } + + private SafeDeflateStreamHandle() : base(IntPtr.Zero, true) + { + } + + override protected bool ReleaseHandle() + { + DeflateStreamNative.CloseZStream(handle); + return true; + } + } } } |