diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs index 3f84bed71529e..bd0f464b0733f 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs @@ -179,15 +179,21 @@ private ParsingResult ParseRawPath(Encoding encoding) current = _rawPath[index]; if (current == '%') { - // Assert is enough, since http.sys accepted the request string already. This should never happen. - Debug.Assert(index + 2 < _rawPath.Length, "Expected >=2 characters after '%' (e.g. %2F)"); + if (index + 2 >= _rawPath.Length) + { + // Not enough data for a percent encoded byte. + return ParsingResult.InvalidString; + } index++; current = _rawPath[index]; if (current == 'u' || current == 'U') { - // We found "%u" which means, we have a Unicode code point of the form "%uXXXX". - Debug.Assert(index + 4 < _rawPath.Length, "Expected >=4 characters after '%u' (e.g. %u0062)"); + if (index + 4 >= _rawPath.Length) + { + // Not enough data for "%uXXXX". + return ParsingResult.InvalidString; + } // Decode the content of rawOctets into percent encoded UTF-8 characters and append them // to requestUriString. diff --git a/src/libraries/System.Net.HttpListener/tests/InvalidClientRequestTests.cs b/src/libraries/System.Net.HttpListener/tests/InvalidClientRequestTests.cs index 3ee33e1b64bef..739c5b2711f34 100644 --- a/src/libraries/System.Net.HttpListener/tests/InvalidClientRequestTests.cs +++ b/src/libraries/System.Net.HttpListener/tests/InvalidClientRequestTests.cs @@ -97,6 +97,14 @@ public static IEnumerable InvalidRequest_TestData() // ? prior to path and query. This may or may not fail, depending on the OS, but in either case it shouldn't crash. yield return new object[] { "GET http://ab?cd{path} HTTP/1.1", null, null, null, "" }; + + // Path ending with an incomplete percent encoded byte or "%uXXXX" + yield return new object[] { "GET /foo/% HTTP/1.1", null, null, null, "" }; + yield return new object[] { "GET /foo/%2 HTTP/1.1", null, null, null, "" }; + yield return new object[] { "GET /foo/%u HTTP/1.1", null, null, null, "" }; + yield return new object[] { "GET /foo/%uF HTTP/1.1", null, null, null, "" }; + yield return new object[] { "GET /foo/%uFF HTTP/1.1", null, null, null, "" }; + yield return new object[] { "GET /foo/%uFFF HTTP/1.1", null, null, null, "" }; } [ActiveIssue("https://github.com/dotnet/runtime/issues/2284", TestRuntimes.Mono)]