From ec5471c248a944ff7a1d642c1200d49ab349bef1 Mon Sep 17 00:00:00 2001 From: Kevin Gosse Date: Wed, 5 Jan 2022 19:46:20 +0100 Subject: [PATCH] Handle race condition when HttpListener is stopped or closed (#63394) * Throw a HttpListenerException if the session is null * Add similar check to BeginGetContext * Address PR feedback * Remove trailing spaces --- .../Net/Windows/HttpListener.Windows.cs | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs index 63c96497909f3..48076f1b39a82 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs @@ -508,7 +508,14 @@ public HttpListenerContext GetContext() uint size = 4096; ulong requestId = 0; memoryBlob = new SyncRequestContext((int)size); - HttpListenerSession session = _currentSession!; + HttpListenerSession? session = _currentSession; + + // Because there is no synchronization, the listener can be stopped or closed while the method is executing, + // resulting in a null session + if (session == null) + { + throw new HttpListenerException((int)Interop.HttpApi.ERROR_INVALID_PARAMETER); + } while (true) { @@ -617,10 +624,20 @@ public IAsyncResult BeginGetContext(AsyncCallback? callback, object? state) { throw new InvalidOperationException(SR.Format(SR.net_listener_mustcall, "Start()")); } + + HttpListenerSession? session = _currentSession; + + // Because there is no synchronization, the listener can be stopped or closed while the method is executing, + // resulting in a null session + if (session == null) + { + throw new HttpListenerException((int)Interop.HttpApi.ERROR_INVALID_PARAMETER); + } + // prepare the ListenerAsyncResult object (this will have it's own // event that the user can wait on for IO completion - which means we // need to signal it when IO completes) - asyncResult = new ListenerAsyncResult(_currentSession!, state, callback); + asyncResult = new ListenerAsyncResult(session, state, callback); uint statusCode = asyncResult.QueueBeginGetContext(); if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING)