@@ -158,8 +158,11 @@ protected override void Dispose(bool disposing)
158158 SafeSslHandle sslContext = _sslContext ;
159159 if ( null != sslContext )
160160 {
161- _inputBuffer . Dispose ( ) ;
162- _outputBuffer . Dispose ( ) ;
161+ lock ( _sslContext )
162+ {
163+ _inputBuffer . Dispose ( ) ;
164+ _outputBuffer . Dispose ( ) ;
165+ }
163166 sslContext . Dispose ( ) ;
164167 }
165168 }
@@ -178,18 +181,21 @@ private static unsafe int WriteToConnection(IntPtr connection, byte* data, void*
178181 // but if we were to pool the buffers we would have a potential use-after-free issue.
179182 try
180183 {
181- ulong length = ( ulong ) * dataLength ;
182- Debug . Assert ( length <= int . MaxValue ) ;
184+ lock ( context )
185+ {
186+ ulong length = ( ulong ) * dataLength ;
187+ Debug . Assert ( length <= int . MaxValue ) ;
183188
184- int toWrite = ( int ) length ;
185- var inputBuffer = new ReadOnlySpan < byte > ( data , toWrite ) ;
189+ int toWrite = ( int ) length ;
190+ var inputBuffer = new ReadOnlySpan < byte > ( data , toWrite ) ;
186191
187- context . _outputBuffer . EnsureAvailableSpace ( toWrite ) ;
188- inputBuffer . CopyTo ( context . _outputBuffer . AvailableSpan ) ;
189- context . _outputBuffer . Commit ( toWrite ) ;
190- // Since we can enqueue everything, no need to re-assign *dataLength.
192+ context . _outputBuffer . EnsureAvailableSpace ( toWrite ) ;
193+ inputBuffer . CopyTo ( context . _outputBuffer . AvailableSpan ) ;
194+ context . _outputBuffer . Commit ( toWrite ) ;
195+ // Since we can enqueue everything, no need to re-assign *dataLength.
191196
192- return OSStatus_noErr ;
197+ return OSStatus_noErr ;
198+ }
193199 }
194200 catch ( Exception e )
195201 {
@@ -207,29 +213,32 @@ private static unsafe int ReadFromConnection(IntPtr connection, byte* data, void
207213
208214 try
209215 {
210- ulong toRead = ( ulong ) * dataLength ;
211-
212- if ( toRead == 0 )
216+ lock ( context )
213217 {
214- return OSStatus_noErr ;
215- }
218+ ulong toRead = ( ulong ) * dataLength ;
216219
217- uint transferred = 0 ;
220+ if ( toRead == 0 )
221+ {
222+ return OSStatus_noErr ;
223+ }
218224
219- if ( context . _inputBuffer . ActiveLength == 0 )
220- {
221- * dataLength = ( void * ) 0 ;
222- return OSStatus_errSSLWouldBlock ;
223- }
225+ uint transferred = 0 ;
224226
225- int limit = Math . Min ( ( int ) toRead , context . _inputBuffer . ActiveLength ) ;
227+ if ( context . _inputBuffer . ActiveLength == 0 )
228+ {
229+ * dataLength = ( void * ) 0 ;
230+ return OSStatus_errSSLWouldBlock ;
231+ }
232+
233+ int limit = Math . Min ( ( int ) toRead , context . _inputBuffer . ActiveLength ) ;
226234
227- context . _inputBuffer . ActiveSpan . Slice ( 0 , limit ) . CopyTo ( new Span < byte > ( data , limit ) ) ;
228- context . _inputBuffer . Discard ( limit ) ;
229- transferred = ( uint ) limit ;
235+ context . _inputBuffer . ActiveSpan . Slice ( 0 , limit ) . CopyTo ( new Span < byte > ( data , limit ) ) ;
236+ context . _inputBuffer . Discard ( limit ) ;
237+ transferred = ( uint ) limit ;
230238
231- * dataLength = ( void * ) transferred ;
232- return OSStatus_noErr ;
239+ * dataLength = ( void * ) transferred ;
240+ return OSStatus_noErr ;
241+ }
233242 }
234243 catch ( Exception e )
235244 {
@@ -241,24 +250,30 @@ private static unsafe int ReadFromConnection(IntPtr connection, byte* data, void
241250
242251 internal void Write ( ReadOnlySpan < byte > buf )
243252 {
244- _inputBuffer . EnsureAvailableSpace ( buf . Length ) ;
245- buf . CopyTo ( _inputBuffer . AvailableSpan ) ;
246- _inputBuffer . Commit ( buf . Length ) ;
253+ lock ( _sslContext )
254+ {
255+ _inputBuffer . EnsureAvailableSpace ( buf . Length ) ;
256+ buf . CopyTo ( _inputBuffer . AvailableSpan ) ;
257+ _inputBuffer . Commit ( buf . Length ) ;
258+ }
247259 }
248260
249261 internal int BytesReadyForConnection => _outputBuffer . ActiveLength ;
250262
251263 internal byte [ ] ? ReadPendingWrites ( )
252264 {
253- if ( _outputBuffer . ActiveLength == 0 )
265+ lock ( _sslContext )
254266 {
255- return null ;
256- }
267+ if ( _outputBuffer . ActiveLength == 0 )
268+ {
269+ return null ;
270+ }
257271
258- byte [ ] buffer = _outputBuffer . ActiveSpan . ToArray ( ) ;
259- _outputBuffer . Discard ( _outputBuffer . ActiveLength ) ;
272+ byte [ ] buffer = _outputBuffer . ActiveSpan . ToArray ( ) ;
273+ _outputBuffer . Discard ( _outputBuffer . ActiveLength ) ;
260274
261- return buffer ;
275+ return buffer ;
276+ }
262277 }
263278
264279 internal int ReadPendingWrites ( byte [ ] buf , int offset , int count )
@@ -268,12 +283,15 @@ internal int ReadPendingWrites(byte[] buf, int offset, int count)
268283 Debug . Assert ( count >= 0 ) ;
269284 Debug . Assert ( count <= buf . Length - offset ) ;
270285
271- int limit = Math . Min ( count , _outputBuffer . ActiveLength ) ;
286+ lock ( _sslContext )
287+ {
288+ int limit = Math . Min ( count , _outputBuffer . ActiveLength ) ;
272289
273- _outputBuffer . ActiveSpan . Slice ( 0 , limit ) . CopyTo ( new Span < byte > ( buf , offset , limit ) ) ;
274- _outputBuffer . Discard ( limit ) ;
290+ _outputBuffer . ActiveSpan . Slice ( 0 , limit ) . CopyTo ( new Span < byte > ( buf , offset , limit ) ) ;
291+ _outputBuffer . Discard ( limit ) ;
275292
276- return limit ;
293+ return limit ;
294+ }
277295 }
278296
279297 private static readonly SslProtocols [ ] s_orderedSslProtocols = new SslProtocols [ 5 ]
0 commit comments