diff --git a/src/libraries/System.Net.Requests/src/Resources/Strings.resx b/src/libraries/System.Net.Requests/src/Resources/Strings.resx index f8ac54eb739cdd..05b94042590c8c 100644 --- a/src/libraries/System.Net.Requests/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Requests/src/Resources/Strings.resx @@ -195,6 +195,9 @@ The underlying connection was closed: An unexpected error occurred on a receive + + CRLF character pair is not allowed in FtpWebRequest inputs. + The remote name could not be resolved diff --git a/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs b/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs index 35eefb9c38cbba..ffba72c9315d28 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs @@ -1118,6 +1118,11 @@ private string GetPortCommandLine() /// private static string FormatFtpCommand(string command, string? parameter) { + if (parameter is not null && parameter.Contains("\r\n", StringComparison.Ordinal)) + { + throw new FormatException(SR.net_ftp_no_newlines); + } + return string.IsNullOrEmpty(parameter) ? command + "\r\n" : command + " " + parameter + "\r\n"; diff --git a/src/libraries/System.Net.Requests/src/System/Net/FtpWebRequest.cs b/src/libraries/System.Net.Requests/src/System/Net/FtpWebRequest.cs index 5a6009240fd921..b27873e9edb233 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/FtpWebRequest.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/FtpWebRequest.cs @@ -486,6 +486,9 @@ internal FtpWebRequest(Uri uri) if ((object)uri.Scheme != (object)Uri.UriSchemeFtp) throw new ArgumentOutOfRangeException(nameof(uri)); + if (uri.OriginalString.Contains("\r\n", StringComparison.Ordinal)) + throw new FormatException(SR.net_ftp_no_newlines); + _timerCallback = new TimerThread.Callback(TimerCallback); _syncObject = new object(); diff --git a/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs b/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs index d1f5e58b3492b5..c2b7ad12524003 100644 --- a/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs +++ b/src/libraries/System.Net.Requests/tests/FtpWebRequestTest.cs @@ -203,6 +203,27 @@ public void Ftp_RenameFileSubDir_Success(FtpExecutionMode mode) Assert.False(DirExists(mode, dir)); } + [Fact] + public void Ftp_Ignore_NewLine_Constructor_Throws_FormatException() + { + string uri = absoluteUri + Guid.NewGuid().ToString(); + + Assert.Throws(() => WebRequest.Create($"{uri}\r\n{WebRequestMethods.Ftp.AppendFile} {Guid.NewGuid().ToString()}")); + } + + [ConditionalFact(nameof(LocalServerAvailable))] + public void Ftp_Ignore_NewLine_GetRequestStream_And_GetResponse_Throws_FormatException_As_InnerException() + { + FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(absoluteUri + Guid.NewGuid().ToString()); + ftpWebRequest.Method = "APPE"; + ftpWebRequest.Credentials = new NetworkCredential("test\r\ntest2", "test\r\ntest2"); + var requestException = Assert.Throws(() => ftpWebRequest.GetRequestStream()); + Assert.True(requestException.InnerException is FormatException); + + var responseException = Assert.Throws(() => ftpWebRequest.GetResponse()); + Assert.True(responseException.InnerException is FormatException); + } + private static async Task DoAsync(FtpWebRequest request, MemoryStream requestBody) { if (requestBody != null)