From d66eb5ce6257c994de2025be35c3f0db6b23e3b9 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Fri, 4 Aug 2023 23:52:04 +0200 Subject: [PATCH] Fix HttpListener path parsing for trailing % (#90028) --- .../System/Net/HttpListenerRequestUriBuilder.cs | 14 ++++++++++---- .../tests/InvalidClientRequestTests.cs | 8 ++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) 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 3f84bed71529eb..bd0f464b0733fc 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 3ee33e1b64befb..739c5b2711f345 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)]