diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx index 501ca3c8f9740..a6972e36a6be5 100644 --- a/src/libraries/System.Net.Http/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx @@ -157,7 +157,7 @@ Invalid range. At least one of the two parameters must not be null. - New-line characters in header values must be followed by a white-space character. + New-line characters are not allowed in header values. Cannot write more bytes to the buffer than the configured maximum buffer size: {0}. @@ -217,7 +217,7 @@ The field cannot be longer than {0} characters. - Value for header '{0}' contains invalid new-line characters. Value: '{1}'. + Value for header '{0}' contains new-line characters. Value: '{1}'. The 'q' value is invalid: '{0}'. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs index 2b6538028e17b..a3197527d80a6 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs @@ -38,6 +38,7 @@ public AuthenticationHeaderValue(string scheme) public AuthenticationHeaderValue(string scheme, string? parameter) { HeaderUtilities.CheckValidToken(scheme, nameof(scheme)); + HttpHeaders.CheckContainsNewLine(parameter); _scheme = scheme; _parameter = parameter; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/GenericHeaderParser.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/GenericHeaderParser.cs index 106c7b3ee96c3..c6ec5e5b0b766 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/GenericHeaderParser.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/GenericHeaderParser.cs @@ -119,7 +119,7 @@ private static int ParseMultipleEntityTags(string value, int startIndex, out obj /// private static int ParseWithoutValidation(string value, int startIndex, out object? parsedValue) { - if (HttpRuleParser.ContainsInvalidNewLine(value, startIndex)) + if (HttpRuleParser.ContainsNewLine(value, startIndex)) { parsedValue = null; return 0; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs index d52a92875a6a8..c31e628159db0 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs @@ -221,7 +221,7 @@ internal bool TryGetValues(HeaderDescriptor descriptor, [NotNullWhen(true)] out internal bool Contains(HeaderDescriptor descriptor) { // We can't just call headerStore.ContainsKey() since after parsing the value the header may not exist - // anymore (if the value contains invalid newline chars, we remove the header). So try to parse the + // anymore (if the value contains newline chars, we remove the header). So try to parse the // header value. return _headerStore != null && TryGetAndParseHeaderInfo(descriptor, out _); } @@ -318,7 +318,7 @@ private IEnumerator>> GetEnumeratorCore // values. if (!ParseRawHeaderValues(descriptor, info, removeEmptyHeader: false)) { - // We have an invalid header value (contains invalid newline chars). Delete it. + // We have an invalid header value (contains newline chars). Delete it. _headerStore.Remove(descriptor); } else @@ -726,18 +726,17 @@ private bool ParseRawHeaderValues(HeaderDescriptor descriptor, HeaderStoreItemIn } // At this point all values are either in info.ParsedValue, info.InvalidValue, or were removed since they - // contain invalid newline chars. Reset RawValue. + // contain newline chars. Reset RawValue. info.RawValue = null; - // During parsing, we removed the value since it contains invalid newline chars. Return false to indicate that + // During parsing, we removed the value since it contains newline chars. Return false to indicate that // this is an empty header. If the caller specified to remove empty headers, we'll remove the header before // returning. if ((info.InvalidValue == null) && (info.ParsedValue == null)) { if (removeEmptyHeader) { - // After parsing the raw value, no value is left because all values contain invalid newline - // chars. + // After parsing the raw value, no value is left because all values contain newline chars. Debug.Assert(_headerStore != null); _headerStore.Remove(descriptor); } @@ -754,7 +753,7 @@ private static void ParseMultipleRawHeaderValues(HeaderDescriptor descriptor, He { foreach (string rawValue in rawValues) { - if (!ContainsInvalidNewLine(rawValue, descriptor.Name)) + if (!ContainsNewLine(rawValue, descriptor.Name)) { AddParsedValue(info, rawValue); } @@ -779,7 +778,7 @@ private static void ParseSingleRawHeaderValue(HeaderDescriptor descriptor, Heade if (descriptor.Parser == null) { - if (!ContainsInvalidNewLine(rawValue, descriptor.Name)) + if (!ContainsNewLine(rawValue, descriptor.Name)) { AddParsedValue(info, rawValue); } @@ -868,7 +867,7 @@ private static bool TryParseAndAddRawHeaderValue(HeaderDescriptor descriptor, He } else { - if (!ContainsInvalidNewLine(value, descriptor.Name) && addWhenInvalid) + if (!ContainsNewLine(value, descriptor.Name) && addWhenInvalid) { AddInvalidValue(info, value); } @@ -885,7 +884,7 @@ private static bool TryParseAndAddRawHeaderValue(HeaderDescriptor descriptor, He } Debug.Assert(value != null); - if (!ContainsInvalidNewLine(value, descriptor.Name) && addWhenInvalid) + if (!ContainsNewLine(value, descriptor.Name) && addWhenInvalid) { AddInvalidValue(info, value ?? string.Empty); } @@ -973,8 +972,8 @@ private void ParseAndAddValue(HeaderDescriptor descriptor, HeaderStoreItemInfo i if (descriptor.Parser == null) { // If we don't have a parser for the header, we consider the value valid if it doesn't contains - // invalid newline characters. We add the values as "parsed value". Note that we allow empty values. - CheckInvalidNewLine(value); + // newline characters. We add the values as "parsed value". Note that we allow empty values. + CheckContainsNewLine(value); AddParsedValue(info, value ?? string.Empty); return; } @@ -1077,22 +1076,22 @@ private bool TryGetHeaderDescriptor(string name, out HeaderDescriptor descriptor return false; } - private static void CheckInvalidNewLine(string? value) + internal static void CheckContainsNewLine(string? value) { if (value == null) { return; } - if (HttpRuleParser.ContainsInvalidNewLine(value)) + if (HttpRuleParser.ContainsNewLine(value)) { throw new FormatException(SR.net_http_headers_no_newlines); } } - private static bool ContainsInvalidNewLine(string value, string name) + private static bool ContainsNewLine(string value, string name) { - if (HttpRuleParser.ContainsInvalidNewLine(value)) + if (HttpRuleParser.ContainsNewLine(value)) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(null, SR.Format(SR.net_http_log_headers_no_newlines, name, value)); return true; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpRequestHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpRequestHeaders.cs index f3035cc6687b3..1731a954bf0a8 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpRequestHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpRequestHeaders.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; namespace System.Net.Http.Headers { @@ -102,6 +101,8 @@ public string? From value = null; } + CheckContainsNewLine(value); + SetOrRemoveParsedValue(KnownHeaders.From.Descriptor, value); } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderParser.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderParser.cs index cd9884eff1678..e8d6e5c15a33a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderParser.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderParser.cs @@ -7,7 +7,6 @@ namespace System.Net.Http.Headers { internal sealed class MediaTypeHeaderParser : BaseHeaderParser { - private readonly bool _supportsMultipleValues; private readonly Func _mediaTypeCreator; internal static readonly MediaTypeHeaderParser SingleValueParser = new MediaTypeHeaderParser(false, CreateMediaType); @@ -18,8 +17,6 @@ private MediaTypeHeaderParser(bool supportsMultipleValues, Func + throw new FormatException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_headers_invalid_value, value)); } private static NameValueHeaderValue CreateNameValue() diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs index 72fed31d31863..2e7390099282b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Globalization; using System.Text; namespace System.Net.Http @@ -141,20 +140,6 @@ internal static int GetWhitespaceLength(string input, int startIndex) continue; } - if (c == '\r') - { - // If we have a #13 char, it must be followed by #10 and then at least one SP or HT. - if ((current + 2 < input.Length) && (input[current + 1] == '\n')) - { - char spaceOrTab = input[current + 2]; - if ((spaceOrTab == ' ') || (spaceOrTab == '\t')) - { - current += 3; - continue; - } - } - } - return current - startIndex; } @@ -162,42 +147,9 @@ internal static int GetWhitespaceLength(string input, int startIndex) return input.Length - startIndex; } - internal static bool ContainsInvalidNewLine(string value) + internal static bool ContainsNewLine(string value, int startIndex = 0) { - return ContainsInvalidNewLine(value, 0); - } - - internal static bool ContainsInvalidNewLine(string value, int startIndex) - { - // Search for newlines followed by non-whitespace: This is not allowed in any header (be it a known or - // custom header). E.g. "value\r\nbadformat: header" is invalid. However "value\r\n goodformat: header" - // is valid: newlines followed by whitespace are allowed in header values. - int current = startIndex; - while (current < value.Length) - { - if (value[current] == '\r') - { - int char10Index = current + 1; - if ((char10Index < value.Length) && (value[char10Index] == '\n')) - { - current = char10Index + 1; - - if (current == value.Length) - { - return true; // We have a string terminating with \r\n. This is invalid. - } - - char c = value[current]; - if ((c != ' ') && (c != '\t')) - { - return true; - } - } - } - current++; - } - - return false; + return value.AsSpan(startIndex).IndexOfAny('\r', '\n') != -1; } internal static int GetNumberLength(string input, int startIndex, bool allowDecimal) @@ -331,7 +283,7 @@ internal static HttpParseResult GetQuotedPairLength(string input, int startIndex } // TEXT = - // LWS = [CRLF] 1*( SP | HT ) + // LWS = SP | HT // CTL = // // Since we don't really care about the content of a quoted string or comment, we're more tolerant and @@ -370,8 +322,15 @@ private static HttpParseResult GetExpressionLength(string input, int startIndex, continue; } + char c = input[current]; + + if (c == '\r' || c == '\n') + { + return HttpParseResult.InvalidFormat; + } + // If we support nested expressions and we find an open-char, then parse the nested expressions. - if (supportsNesting && (input[current] == openChar)) + if (supportsNesting && (c == openChar)) { // Check if we exceeded the number of nested calls. if (nestedCount > MaxNestedCount) diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/AltSvcHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/AltSvcHeaderParserTest.cs index 3349ba6215f3a..c40eef9eba321 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/AltSvcHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/AltSvcHeaderParserTest.cs @@ -1,14 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Net.Http.Headers; using Xunit; -using Xunit.Sdk; namespace System.Net.Http.Tests { diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ByteArrayHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ByteArrayHeaderParserTest.cs index d5c7147ded0be..8a28534b47962 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ByteArrayHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ByteArrayHeaderParserTest.cs @@ -1,10 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Net.Http.Headers; -using System.Text; using Xunit; diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ContentDispositionHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ContentDispositionHeaderValueTest.cs index be4e0e65001e6..cb44f49b76781 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ContentDispositionHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ContentDispositionHeaderValueTest.cs @@ -1,11 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -487,8 +485,8 @@ public void GetDispositionTypeLength_DifferentValidScenarios_AllReturnNonZero() Assert.Equal("custom", value.Parameters.ElementAt(0).Name); Assert.Null(value.Parameters.ElementAt(0).Value); - Assert.Equal(40, ContentDispositionHeaderValue.GetDispositionTypeLength( - "inline ; custom =\r\n \"x\" ; name = myName , next", 0, out result)); + Assert.Equal(38, ContentDispositionHeaderValue.GetDispositionTypeLength( + "inline ; custom = \"x\" ; name = myName , next", 0, out result)); value = (ContentDispositionHeaderValue)result; Assert.Equal("inline", value.DispositionType); Assert.Equal("myName", value.Name); @@ -535,14 +533,14 @@ public void GetDispositionTypeLength_DifferentInvalidScenarios_AllReturnZero() public void Parse_SetOfValidValueStrings_ParsedCorrectly() { ContentDispositionHeaderValue expected = new ContentDispositionHeaderValue("inline"); - CheckValidParse("\r\n inline ", expected); + CheckValidParse(" inline ", expected); CheckValidParse("inline", expected); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // Content-Disposition parser. expected.Name = "myName"; - CheckValidParse("\r\n inline ; name = myName ", expected); + CheckValidParse(" inline ; name = myName ", expected); CheckValidParse(" inline;name=myName", expected); expected.Name = null; @@ -565,35 +563,7 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse("inline; name=myName,"); CheckInvalidParse("inline; name=my\u4F1AName"); CheckInvalidParse("inline/"); - } - - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - ContentDispositionHeaderValue expected = new ContentDispositionHeaderValue("inline"); - CheckValidTryParse("\r\n inline ", expected); - CheckValidTryParse("inline", expected); - - // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. - // The purpose of this test is to verify that these other parsers are combined correctly to build a - // Content-Disposition parser. - expected.Name = "myName"; - CheckValidTryParse("\r\n inline ; name = myName ", expected); - CheckValidTryParse(" inline;name=myName", expected); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse(""); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(null); - CheckInvalidTryParse("inline\u4F1A"); - CheckInvalidTryParse("inline ,"); - CheckInvalidTryParse("inline,"); - CheckInvalidTryParse("inline; name=myName ,"); - CheckInvalidTryParse("inline; name=myName,"); - CheckInvalidTryParse("text/"); + CheckInvalidParse(" inline ; \r name = myName "); } #region Tests from HenrikN @@ -1209,24 +1179,16 @@ private void CheckValidParse(string input, ContentDispositionHeaderValue expecte { ContentDispositionHeaderValue result = ContentDispositionHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { ContentDispositionHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, ContentDispositionHeaderValue expectedResult) - { - ContentDispositionHeaderValue result = null; Assert.True(ContentDispositionHeaderValue.TryParse(input, out result), input); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - ContentDispositionHeaderValue result = null; - Assert.False(ContentDispositionHeaderValue.TryParse(input, out result), input); + Assert.Throws(() => { ContentDispositionHeaderValue.Parse(input); }); + + Assert.False(ContentDispositionHeaderValue.TryParse(input, out ContentDispositionHeaderValue result), input); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/DateHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/DateHeaderParserTest.cs index 89ce57593e47e..ebb2efe606884 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/DateHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/DateHeaderParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/EntityTagHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/EntityTagHeaderValueTest.cs index 290c53decc668..644c6cb1581a2 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/EntityTagHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/EntityTagHeaderValueTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -140,7 +136,7 @@ public void GetEntityTagLength_DifferentValidScenarios_AllReturnNonZero() // Note that even if after a valid tag & whitespace there are invalid characters, GetEntityTagLength() // will return the length of the valid tag and ignore the invalid characters at the end. It is the callers // responsibility to consider the whole string invalid if after a valid ETag there are invalid chars. - Assert.Equal(11, EntityTagHeaderValue.GetEntityTagLength("\"tag\" \r\n !!", 0, out result)); + Assert.Equal(9, EntityTagHeaderValue.GetEntityTagLength("\"tag\" !!", 0, out result)); Assert.Equal("\"tag\"", result.Tag); Assert.False(result.IsWeak); @@ -198,7 +194,6 @@ public void Parse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidParse("\"tag\"", new EntityTagHeaderValue("\"tag\"")); CheckValidParse(" \"tag\" ", new EntityTagHeaderValue("\"tag\"")); - CheckValidParse("\r\n \"tag\"\r\n ", new EntityTagHeaderValue("\"tag\"")); CheckValidParse("\"tag\"", new EntityTagHeaderValue("\"tag\"")); CheckValidParse("\"tag\u4F1A\"", new EntityTagHeaderValue("\"tag\u4F1A\"")); CheckValidParse("W/\"tag\"", new EntityTagHeaderValue("\"tag\"", true)); @@ -217,32 +212,8 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse("\"tag\" \"tag2\""); CheckInvalidParse("/\"tag\""); CheckInvalidParse("*"); // "any" is not allowed as ETag value. - } - - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse("\"tag\"", new EntityTagHeaderValue("\"tag\"")); - CheckValidTryParse(" \"tag\" ", new EntityTagHeaderValue("\"tag\"")); - CheckValidTryParse("\r\n \"tag\"\r\n ", new EntityTagHeaderValue("\"tag\"")); - CheckValidTryParse("\"tag\"", new EntityTagHeaderValue("\"tag\"")); - CheckValidTryParse("\"tag\u4F1A\"", new EntityTagHeaderValue("\"tag\u4F1A\"")); - CheckValidTryParse("W/\"tag\"", new EntityTagHeaderValue("\"tag\"", true)); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" !"); - CheckInvalidTryParse("tag\" !"); - CheckInvalidTryParse("!\"tag\""); - CheckInvalidTryParse("\"tag\","); - CheckInvalidTryParse("\"tag\" \"tag2\""); - CheckInvalidTryParse("/\"tag\""); - CheckInvalidTryParse("*"); // "any" is not allowed as ETag value. + CheckInvalidParse("\r\n \"tag\"\r\n "); + CheckInvalidParse("\"tag\" \r\n !!"); } #region Helper methods @@ -251,24 +222,16 @@ private void CheckValidParse(string input, EntityTagHeaderValue expectedResult) { EntityTagHeaderValue result = EntityTagHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { EntityTagHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, EntityTagHeaderValue expectedResult) - { - EntityTagHeaderValue result = null; Assert.True(EntityTagHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - EntityTagHeaderValue result = null; - Assert.False(EntityTagHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { EntityTagHeaderValue.Parse(input); }); + + Assert.False(EntityTagHeaderValue.TryParse(input, out EntityTagHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/EntityTagParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/EntityTagParserTest.cs index 938fce5615eed..3549295f2d403 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/EntityTagParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/EntityTagParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -34,8 +30,8 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() CheckValidParsedValue(" * ,", 1, EntityTagHeaderValue.Any, 5, true); CheckValidParsedValue(" \"tag\" ", 0, new EntityTagHeaderValue("\"tag\""), 7, false); CheckValidParsedValue(" \"tag\" ,", 0, new EntityTagHeaderValue("\"tag\""), 8, true); - CheckValidParsedValue("\r\n \"tag\"\r\n ", 0, new EntityTagHeaderValue("\"tag\""), 11, false); - CheckValidParsedValue("\r\n \"tag\"\r\n , ", 0, new EntityTagHeaderValue("\"tag\""), 14, true); + CheckValidParsedValue(" \"tag\" ", 0, new EntityTagHeaderValue("\"tag\""), 7, false); + CheckValidParsedValue(" \"tag\" , ", 0, new EntityTagHeaderValue("\"tag\""), 10, true); CheckValidParsedValue("!\"tag\"", 1, new EntityTagHeaderValue("\"tag\""), 6, false); CheckValidParsedValue("!\"tag\"", 1, new EntityTagHeaderValue("\"tag\""), 6, true); CheckValidParsedValue("//\"tag\u4F1A\"", 2, new EntityTagHeaderValue("\"tag\u4F1A\""), 8, false); @@ -62,6 +58,8 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("\"tag\" \"tag2\"", 0, false); CheckInvalidParsedValue("W/\"tag\"", 1, false); CheckInvalidParsedValue("*", 0, false); // "any" is not allowed as ETag value. + CheckInvalidParsedValue("\r\n \"tag\"\r\n ", 0, false); + CheckInvalidParsedValue("\r\n \"tag\"\r\n , ", 0, false); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/HostParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/HostParserTest.cs index 91eaa0760a8ff..c149c59170ebd 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/HostParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/HostParserTest.cs @@ -22,7 +22,6 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidParsedValue("host", 0, "host", 4); CheckValidParsedValue(" host ", 0, "host", 6); - CheckValidParsedValue("\r\n host\r\n ", 0, "host", 10); CheckValidParsedValue("!host", 1, "host", 5); CheckValidParsedValue("!host:50", 1, "host:50", 8); CheckValidParsedValue("//host\u4F1A", 2, "host\u4F1A", 7); @@ -54,6 +53,7 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("host ,", 0); CheckInvalidParsedValue("/", 0); CheckInvalidParsedValue(" , ", 0); + CheckInvalidParsedValue(" host\r\n ", 0); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/MailAddressParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/MailAddressParserTest.cs deleted file mode 100644 index 917c6e0b35b14..0000000000000 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/MailAddressParserTest.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Mail; -using System.Net.Http.Headers; -using System.Text; - -using Xunit; - -namespace System.Net.Http.Tests -{ - public class MailAddressParserTest - { - [Fact] - public void Properties_ReadValues_MatchExpectation() - { - HttpHeaderParser parser = GenericHeaderParser.MailAddressParser; - Assert.False(parser.SupportsMultipleValues); - Assert.Null(parser.Comparer); - } - - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - // We don't need to validate all possible date values, since they're already tested MailAddress. - // Just make sure the parser calls MailAddressParser with correct parameters (like startIndex must be - // honored). - - // Note that we still have trailing whitespace since we don't do the parsing of the email address. - CheckValidParsedValue("!! info@example.com ", 2, "info@example.com ", 27); - CheckValidParsedValue("\r\n \"My name\" info@example.com", 0, - "\"My name\" info@example.com", 29); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidParsedValue("[info@example.com", 0); - CheckInvalidParsedValue("info@example.com\r\nother", 0); - CheckInvalidParsedValue("info@example.com\r\n other", 0); - CheckInvalidParsedValue("info@example.com\r\n", 0); - CheckInvalidParsedValue("info@example.com,", 0); - CheckInvalidParsedValue("\r\ninfo@example.com", 0); - CheckInvalidParsedValue(null, 0); - CheckInvalidParsedValue(string.Empty, 0); - CheckInvalidParsedValue(" ", 2); - } - - #region Helper methods - - private void CheckValidParsedValue(string input, int startIndex, string expectedResult, - int expectedIndex) - { - HttpHeaderParser parser = GenericHeaderParser.MailAddressParser; - object result = null; - Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), - string.Format("TryParse returned false: {0}", input)); - Assert.Equal(expectedIndex, startIndex); - Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParsedValue(string input, int startIndex) - { - HttpHeaderParser parser = GenericHeaderParser.MailAddressParser; - object result = null; - int newIndex = startIndex; - Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), - string.Format("TryParse returned true: {0}", input)); - Assert.Null(result); - Assert.Equal(startIndex, newIndex); - } - #endregion - } -} diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueParserTest.cs index 71604d4385d28..967cac75c5533 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -50,6 +46,12 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("name value", 0); CheckInvalidParsedValue("name=,value", 0); CheckInvalidParsedValue("\u4F1A", 0); + CheckInvalidParsedValue("name=\nvalue", 0); + CheckInvalidParsedValue("name=val\nue", 0); + CheckInvalidParsedValue("name=value\n", 0); + CheckInvalidParsedValue("\"name=\nvalue\"", 0); + CheckInvalidParsedValue("\"name=val\nue\"", 0); + CheckInvalidParsedValue("\"name=value\n\"", 0); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueWithParametersParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueWithParametersParserTest.cs index 130927ad55b81..916302a1bba9d 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueWithParametersParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueWithParametersParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -52,9 +48,9 @@ public void Parse_InvalidValue_Throw() public void TryParse_SetOfValidValueStrings_ParsedCorrectly() { NameValueWithParametersHeaderValue expected = new NameValueWithParametersHeaderValue("custom"); - CheckValidParsedValue("\r\n custom ", 0, expected, 11); + CheckValidParsedValue(" custom ", 0, expected, 9); CheckValidParsedValue("custom", 0, expected, 6); - CheckValidParsedValue(",, ,\r\n custom , chunked", 0, expected, 17); + CheckValidParsedValue(",, , custom , chunked", 0, expected, 15); // Note that even if the whole string is invalid, the first "Expect" value is valid. When the parser // gets called again using the result-index (9), then it fails: I.e. we have 1 valid "Expect" value @@ -65,7 +61,7 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() // The purpose of this test is to verify that these other parsers are combined correctly to build a // transfer-coding parser. expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidParsedValue("\r\n custom ; name = value ", 0, expected, 28); + CheckValidParsedValue(" custom ; name = value ", 0, expected, 26); CheckValidParsedValue(" custom;name=value", 2, expected, 19); CheckValidParsedValue(" custom ; name=value", 2, expected, 21); @@ -81,6 +77,12 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("custom\u4F1A", 0); CheckInvalidParsedValue("custom; name=value;", 0); CheckInvalidParsedValue("custom; name1=value1; name2=value2;", 0); + CheckInvalidParsedValue("\r\n custom ", 0); + CheckInvalidParsedValue(",, ,\r\n custom , chunked", 0); + CheckInvalidParsedValue("\r\n custom ; name = value ", 0); + CheckInvalidParsedValue("custom; name=value\r", 0); + CheckInvalidParsedValue("custom; name=value;\r", 0); + CheckInvalidParsedValue("custom; name=value;\r foo=bar", 0); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/StringWithQualityParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/StringWithQualityParserTest.cs index ef1265db99676..177d773686fc5 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/StringWithQualityParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/StringWithQualityParserTest.cs @@ -26,12 +26,12 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidParsedValue("text", 0, new StringWithQualityHeaderValue("text"), 4); CheckValidParsedValue("text,", 0, new StringWithQualityHeaderValue("text"), 5); - CheckValidParsedValue("\r\n text ; q = 0.5, next_text ", 0, new StringWithQualityHeaderValue("text", 0.5), 19); + CheckValidParsedValue(" text ; q = 0.5, next_text ", 0, new StringWithQualityHeaderValue("text", 0.5), 17); CheckValidParsedValue(" text,next_text ", 2, new StringWithQualityHeaderValue("text"), 7); CheckValidParsedValue(" ,, text, , ,next", 0, new StringWithQualityHeaderValue("text"), 13); CheckValidParsedValue(" ,, text, , ,", 0, new StringWithQualityHeaderValue("text"), 13); - CheckValidParsedValue(", \r\n text \r\n ; \r\n q = 0.123", 0, - new StringWithQualityHeaderValue("text", 0.123), 27); + CheckValidParsedValue(", text ; q = 0.123", 0, + new StringWithQualityHeaderValue("text", 0.123), 21); CheckValidParsedValue(null, 0, null, 0); CheckValidParsedValue(string.Empty, 0, null, 0); @@ -52,6 +52,8 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("t;q\u4F1A=1", 0); CheckInvalidParsedValue("t y", 0); CheckInvalidParsedValue("t;q=1 y", 0); + CheckInvalidParsedValue("\r\n text ; q = 0.5, next_text ", 0); + CheckInvalidParsedValue(", \r\n text \r\n ; \r\n q = 0.123", 0); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/TokenListParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/TokenListParserTest.cs index d6d1dd15c8b28..3500fb9503cff 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/TokenListParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/TokenListParserTest.cs @@ -22,7 +22,7 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidParsedValue("text", 0, "text", 4); CheckValidParsedValue("text,", 0, "text", 5); - CheckValidParsedValue("\r\n text , next_text ", 0, "text", 10); + CheckValidParsedValue(" text , next_text ", 0, "text", 8); CheckValidParsedValue(" text,next_text ", 2, "text", 7); CheckValidParsedValue(" ,, text, , ,next", 0, "text", 13); CheckValidParsedValue(" ,, text, , ,", 0, "text", 13); @@ -39,6 +39,7 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("te\u00E4xt", 0); CheckInvalidParsedValue("text\u4F1A", 0); CheckInvalidParsedValue("\u4F1A", 0); + CheckInvalidParsedValue("\r\n text , next_text ", 0); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/ViaParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/ViaParserTest.cs index 330b7305dec16..155e5b30997ac 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/ViaParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/ViaParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -29,8 +25,8 @@ public void Properties_ReadValues_MatchExpectation() public void TryParse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidParsedValue("X , , 1.1 host, ,next", 1, new ViaHeaderValue("1.1", "host"), 19); - CheckValidParsedValue("X HTTP / x11 192.168.0.1\r\n (comment) , ,next", 1, - new ViaHeaderValue("x11", "192.168.0.1", "HTTP", "(comment)"), 44); + CheckValidParsedValue("X HTTP / x11 192.168.0.1 (comment) , ,next", 1, + new ViaHeaderValue("x11", "192.168.0.1", "HTTP", "(comment)"), 42); CheckValidParsedValue(" ,HTTP/1.1 [::1]", 0, new ViaHeaderValue("1.1", "[::1]", "HTTP"), 16); CheckValidParsedValue("1.1 host", 0, new ViaHeaderValue("1.1", "host"), 8); @@ -54,6 +50,7 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("\u4F1A", 0); CheckInvalidParsedValue("HTTP/test [::1]:80\r(comment)", 0); CheckInvalidParsedValue("HTTP/test [::1]:80\n(comment)", 0); + CheckInvalidParsedValue("X HTTP / x11 192.168.0.1 (comment) , ,next", 0); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HeaderUtilitiesTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HeaderUtilitiesTest.cs index cece26a7c5ff2..64a29bda743dd 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HeaderUtilitiesTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HeaderUtilitiesTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -69,7 +65,7 @@ public void AreEqualCollections_UseSetOfNotEqualCollections_ReturnsFalse() [Fact] public void GetNextNonEmptyOrWhitespaceIndex_UseDifferentInput_MatchExpectation() { - CheckGetNextNonEmptyOrWhitespaceIndex("x , , ,, ,\t\r\n , ,x", 1, true, 18, true); + CheckGetNextNonEmptyOrWhitespaceIndex("x , , ,, ,\t , ,x", 1, true, 16, true); CheckGetNextNonEmptyOrWhitespaceIndex("x , , ", 1, false, 4, true); // stop at the second ',' CheckGetNextNonEmptyOrWhitespaceIndex("x , , ", 1, true, 8, true); CheckGetNextNonEmptyOrWhitespaceIndex(" x", 0, true, 1, false); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs index 6191eb254f3f9..b50b28b56fd1b 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpContentHeadersTest.cs @@ -1,12 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http.Headers; -using System.Text; using System.Threading.Tasks; using Xunit; @@ -72,7 +69,7 @@ public void ContentLength_SetCustomValue_TryComputeLengthNotInvoked() public void ContentLength_UseAddMethod_AddedValueCanBeRetrievedUsingProperty() { _headers = new HttpContentHeaders(new ComputeLengthHttpContent(() => { throw new ShouldNotBeInvokedException(); })); - _headers.TryAddWithoutValidation(HttpKnownHeaderNames.ContentLength, " 68 \r\n "); + _headers.TryAddWithoutValidation(HttpKnownHeaderNames.ContentLength, " 68 "); Assert.Equal(68, _headers.ContentLength); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs index f2a4367c70463..f56f85ac5bd0d 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs @@ -329,60 +329,44 @@ public void TryAddWithoutValidation_AddMultipleValueStringToSingleValueHeaders_M Assert.Equal(1, headers.Parser.TryParseValueCallCount); } - [Fact] - public void TryAddWithoutValidation_AddValueContainingNewLine_NewLineFollowedByWhitespaceIsOKButNewLineFollowedByNonWhitespaceIsRejected() + [Theory] + [MemberData(nameof(HeaderValuesWithNewLines))] + public void TryAddWithoutValidation_AddValueContainingNewLine_Rejected(string headerValue) { - MockHeaders headers = new MockHeaders(); - - // The header parser rejects both of the following values. Both values contain new line chars. According - // to the RFC, LWS supports newlines followed by whitespace. I.e. the first value gets rejected by the - // parser, but added to the list of invalid values. - headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\n other: value"); // OK, LWS is allowed - Assert.Equal(1, headers.Count()); - Assert.Equal(1, headers.First().Value.Count()); - Assert.Equal(invalidHeaderValue + "\r\n other: value", headers.First().Value.First()); - Assert.Equal(1, headers.Parser.TryParseValueCallCount); + var headers = new HttpRequestHeaders(); // This value is considered invalid (newline char followed by non-whitespace). However, since // TryAddWithoutValidation() only causes the header value to be analyzed when it gets actually accessed, no // exception is thrown. Instead the value is discarded and a warning is logged. - headers.Clear(); - headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\nother:value"); - Assert.False(headers.Contains(headers.Descriptor)); - Assert.Equal(0, headers.Count()); + headers.TryAddWithoutValidation("foo", headerValue); - // Adding newline followed by whitespace to a custom header is OK. - headers.Clear(); - headers.TryAddWithoutValidation("custom", "value\r\n other: value"); // OK, LWS is allowed - Assert.Equal(1, headers.Count()); - Assert.Equal(1, headers.First().Value.Count()); - Assert.Equal("value\r\n other: value", headers.First().Value.First()); + Assert.Equal(1, headers.NonValidated.Count); + Assert.Equal(headerValue, headers.NonValidated["foo"].ToString()); - // Adding newline followed by non-whitespace chars is invalid. The value is discarded and a warning is - // logged. - headers.Clear(); - headers.TryAddWithoutValidation("custom", "value\r\nother: value"); - Assert.False(headers.Contains("custom")); + Assert.False(headers.Contains("foo")); Assert.Equal(0, headers.Count()); - // Also ending a value with newline is invalid. Verify that valid values are added. - headers.Clear(); - headers.Parser.TryParseValueCallCount = 0; - headers.TryAddWithoutValidation(headers.Descriptor, rawPrefix + "\rvalid"); - headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\n"); - headers.TryAddWithoutValidation(headers.Descriptor, rawPrefix + "\n," + invalidHeaderValue + "\r\nother"); - Assert.Equal(1, headers.Count()); - Assert.Equal(1, headers.First().Value.Count()); - Assert.Equal(parsedPrefix + "\rvalid", headers.First().Value.First()); - Assert.Equal(4, headers.Parser.TryParseValueCallCount); + // Accessing the header forces parsing and the invalid value is removed + Assert.Equal(0, headers.NonValidated.Count); + headers.Clear(); - headers.TryAddWithoutValidation("custom", "value\r\ninvalid"); - headers.TryAddWithoutValidation("custom", "value\r\n valid"); - headers.TryAddWithoutValidation("custom", "validvalue, invalid\r\nvalue"); + headers.TryAddWithoutValidation("foo", new[] { "valid", headerValue }); + + Assert.Equal(1, headers.NonValidated.Count); + HeaderStringValues values = headers.NonValidated["foo"]; + Assert.Equal(2, values.Count); + Assert.Equal(new[] { "valid", headerValue }, values); + Assert.Equal(1, headers.Count()); Assert.Equal(1, headers.First().Value.Count()); - Assert.Equal("value\r\n valid", headers.First().Value.First()); + Assert.Equal("valid", headers.First().Value.First()); + + // Accessing the header forces parsing and the invalid value is removed + Assert.Equal(1, headers.NonValidated.Count); + values = headers.NonValidated["foo"]; + Assert.Equal(1, values.Count); + Assert.Equal("valid", values.ToString()); } [Fact] @@ -811,22 +795,23 @@ public void Add_SingleAddHeadersWithDifferentCasing_ConsideredTheSameHeader() Assert.Equal(3, headers.GetValues("CuStOm-HeAdEr").Count()); } - [Fact] - public void Add_AddValueContainingNewLine_NewLineFollowedByWhitespaceIsOKButNewLineFollowedByNonWhitespaceIsRejected() + [Theory] + [MemberData(nameof(HeaderValuesWithNewLines))] + public void Add_AddValueContainingNewLine_Rejected(string headerValue) { - MockHeaders headers = new MockHeaders(); + var headers = new HttpRequestHeaders(); - headers.Clear(); - headers.Add("custom", "value\r"); - Assert.Equal(1, headers.Count()); - Assert.Equal(1, headers.First().Value.Count()); - Assert.Equal("value\r", headers.First().Value.First()); + Assert.Throws(() => headers.Add("foo", headerValue)); + Assert.Equal(0, headers.Count()); + Assert.Equal(0, headers.NonValidated.Count); headers.Clear(); - Assert.Throws(() => { headers.Add("custom", new string[] { "valid\n", "invalid\r\nother" }); }); + Assert.Throws(() => headers.Add("foo", new[] { "valid", headerValue })); Assert.Equal(1, headers.Count()); Assert.Equal(1, headers.First().Value.Count()); - Assert.Equal("valid\n", headers.First().Value.First()); + Assert.Equal("valid", headers.First().Value.First()); + Assert.Equal(1, headers.NonValidated.Count); + Assert.Equal("valid", headers.NonValidated["foo"].ToString()); } [Fact] @@ -996,11 +981,11 @@ public void RemoveParsedValue_AddTwoValuesToKnownHeaderAndCompareWithValueThatDi } [Fact] - public void RemoveParsedValue_FirstAddInvalidNewlineCharsValueThenCallRemoveParsedValue_HeaderRemoved() + public void RemoveParsedValue_FirstAddNewlineCharsValueThenCallRemoveParsedValue_HeaderRemoved() { MockHeaders headers = new MockHeaders(); - // Add header value with invalid newline chars. + // Add header value with newline chars. headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\ninvalid"); Assert.Equal(0, headers.Parser.TryParseValueCallCount); @@ -1011,11 +996,11 @@ public void RemoveParsedValue_FirstAddInvalidNewlineCharsValueThenCallRemovePars } [Fact] - public void RemoveParsedValue_FirstAddInvalidNewlineCharsValueThenAddValidValueThenCallAddParsedValue_HeaderRemoved() + public void RemoveParsedValue_FirstAddNewlineCharsValueThenAddValidValueThenCallAddParsedValue_HeaderRemoved() { MockHeaders headers = new MockHeaders(); - // Add header value with invalid newline chars. + // Add header value with newline chars. headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\ninvalid"); headers.TryAddWithoutValidation(headers.Descriptor, rawPrefix + "1"); @@ -1407,11 +1392,11 @@ public void GetParsedValues_AddInvalidValueToHeader_HeaderGetsRemovedAndNullRetu } [Fact] - public void GetParsedValues_GetParsedValuesForKnownHeaderWithInvalidNewlineChars_ReturnsNull() + public void GetParsedValues_GetParsedValuesForKnownHeaderWithNewlineChars_ReturnsNull() { MockHeaders headers = new MockHeaders(); - // Add header value with invalid newline chars. + // Add header value with newline chars. headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\ninvalid"); Assert.Equal(0, headers.Parser.TryParseValueCallCount); @@ -1436,7 +1421,6 @@ public void NonValidated_SetValidAndInvalidHeaderValues_AllHeaderValuesReturned( MockHeaderParser parser = new MockHeaderParser("---"); MockHeaders headers = new MockHeaders(parser); - // Add header value with invalid newline chars. headers.Add(headers.Descriptor, rawPrefix + "1"); headers.TryAddWithoutValidation(headers.Descriptor, "value2,value3"); headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue); @@ -1464,7 +1448,6 @@ public void NonValidated_SetMultipleHeaders_AllHeaderValuesReturned() MockHeaderParser parser = new MockHeaderParser(true); MockHeaders headers = new MockHeaders(parser); - // Add header value with invalid newline chars. headers.Add(headers.Descriptor, rawPrefix + "1"); headers.Add("header2", "value2"); headers.Add("header3", (string)null); @@ -1622,12 +1605,12 @@ public void Contains_CallContainsForExistingHeader_ReturnsTrue() Assert.True(headers.Contains(headers.Descriptor)); // Contains() should trigger parsing of values added with TryAddWithoutValidation(): If the value was invalid, - // i.e. contains invalid newline chars, then the header will be removed from the collection. + // i.e. contains newline chars, then the header will be removed from the collection. Assert.Equal(1, headers.Parser.TryParseValueCallCount); } [Fact] - public void Contains_AddValuesWithInvalidNewlineChars_HeadersGetRemovedWhenCallingContains() + public void Contains_AddValuesWithNewlineChars_HeadersGetRemovedWhenCallingContains() { MockHeaders headers = new MockHeaders(); @@ -1794,11 +1777,11 @@ public void AddParsedValue_UseDifferentAddMethods_AllValuesAddedCorrectly() } [Fact] - public void AddParsedValue_FirstAddInvalidNewlineCharsValueThenCallAddParsedValue_ParsedValueAdded() + public void AddParsedValue_FirstAddNewlineCharsValueThenCallAddParsedValue_ParsedValueAdded() { MockHeaders headers = new MockHeaders(); - // Add header value with invalid newline chars. + // Add header value with newline chars. headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\ninvalid"); Assert.Equal(0, headers.Parser.TryParseValueCallCount); @@ -1811,11 +1794,11 @@ public void AddParsedValue_FirstAddInvalidNewlineCharsValueThenCallAddParsedValu } [Fact] - public void AddParsedValue_FirstAddInvalidNewlineCharsValueThenAddValidValueThenCallAddParsedValue_ParsedValueAdded() + public void AddParsedValue_FirstAddNewlineCharsValueThenAddValidValueThenCallAddParsedValue_ParsedValueAdded() { MockHeaders headers = new MockHeaders(); - // Add header value with invalid newline chars. + // Add header value with newline chars. headers.TryAddWithoutValidation(headers.Descriptor, invalidHeaderValue + "\r\ninvalid"); headers.TryAddWithoutValidation(headers.Descriptor, rawPrefix + "0"); @@ -2212,6 +2195,16 @@ public static IEnumerable GetInvalidHeaderNames() yield return new object[] { "invalid}header" }; } + public static IEnumerable HeaderValuesWithNewLines() + { + foreach (string pattern in new[] { "*", "*foo", "* foo", "foo*", "foo* ", "foo*bar", "foo* bar" }) + foreach (string newLine in new[] { "\r", "\n", "\r\n" }) + foreach (string prefix in new[] { "", "valid, " }) + { + yield return new object[] { prefix + pattern.Replace("*", newLine) }; + } + } + #region Helper methods private class MockHeaders : HttpHeaders diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs index 4ce88a86089b8..81fa6560bc60c 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpRequestHeadersTest.cs @@ -1,12 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; -using System.Net.Mail; -using System.Text; using Xunit; @@ -71,7 +68,7 @@ public void Accept_ReadEmptyProperty_EmptyCollection() public void Accept_UseAddMethod_AddedValueCanBeRetrievedUsingProperty() { headers.TryAddWithoutValidation("Accept", - ",, , ,,text/plain; charset=iso-8859-1; q=1.0,\r\n */xml; charset=utf-8; q=0.5,,,"); + ",, , ,,text/plain; charset=iso-8859-1; q=1.0, */xml; charset=utf-8; q=0.5,,,"); MediaTypeWithQualityHeaderValue value1 = new MediaTypeWithQualityHeaderValue("text/plain"); value1.CharSet = "iso-8859-1"; @@ -100,6 +97,12 @@ public void Accept_UseAddMethodWithInvalidValue_InvalidValueRecognized() Assert.Equal(0, headers.Accept.Count); Assert.Equal(1, headers.GetValues("Accept").Count()); Assert.Equal("text/plain application/xml", headers.GetValues("Accept").First()); + + headers.Clear(); + headers.TryAddWithoutValidation("Accept", "text/plain; charset=iso-8859-1; q=1.0,\r\n */xml; charset=utf-8; q=0.5,,,"); + + Assert.Equal(0, headers.Accept.Count); + Assert.False(headers.Contains("Accept")); } [Fact] @@ -121,7 +124,7 @@ public void AcceptCharset_ReadAndWriteProperty_ValueMatchesPriorSetValue() [Fact] public void AcceptCharset_UseAddMethod_AddedValueCanBeRetrievedUsingProperty() { - headers.TryAddWithoutValidation("Accept-Charset", ", ,,iso-8859-5 , \r\n utf-8 ; q=0.300 ,,,"); + headers.TryAddWithoutValidation("Accept-Charset", ", ,,iso-8859-5 , utf-8 ; q=0.300 ,,,"); Assert.Equal(new StringWithQualityHeaderValue("iso-8859-5"), headers.AcceptCharset.ElementAt(0)); @@ -142,6 +145,11 @@ public void AcceptCharset_UseAddMethodWithInvalidValue_InvalidValueRecognized() Assert.Equal(0, headers.AcceptCharset.Count); Assert.Equal(1, headers.GetValues("Accept-Charset").Count()); Assert.Equal("utf-8; q=1; q=0.3", headers.GetValues("Accept-Charset").First()); + + headers.Clear(); + headers.TryAddWithoutValidation("Accept-Charset", "iso-8859-5, \r\n utf-8; q=0.300"); + Assert.Equal(0, headers.AcceptCharset.Count); + Assert.False(headers.Contains("Accept-Charset")); } [Fact] @@ -480,7 +488,7 @@ public void TE_ReadAndWriteProperty_ValueMatchesPriorSetValue() public void TE_UseAddMethod_AddedValueCanBeRetrievedUsingProperty() { headers.TryAddWithoutValidation("TE", - ",custom1; param1=value1; q=1.0,,\r\n custom2; param2=value2; q=0.5 ,"); + ",custom1; param1=value1; q=1.0,, custom2; param2=value2; q=0.5 ,"); TransferCodingWithQualityHeaderValue value1 = new TransferCodingWithQualityHeaderValue("custom1"); value1.Parameters.Add(new NameValueHeaderValue("param1", "value1")); @@ -762,6 +770,13 @@ public void From_UseAddMethodWithInvalidValue_InvalidValueRecognized() Assert.Equal("info@", headers.GetValues("From").First()); } + [Fact] + public void From_ValueContainsNewLineCharacters_Throws() + { + Assert.Throws(() => headers.From = "Foo\r\nBar"); + Assert.Throws(() => headers.Add("From", "Foo\r\nBar")); + } + [Fact] public void IfModifiedSince_ReadAndWriteProperty_ValueMatchesPriorSetValue() { diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int32NumberHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int32NumberHeaderParserTest.cs index ca38f153c9929..a405bab30621d 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int32NumberHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int32NumberHeaderParserTest.cs @@ -1,12 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -61,8 +56,6 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() CheckValidParsedValue("1234567890", 0, 1234567890, 10); CheckValidParsedValue("0", 0, 0, 1); CheckValidParsedValue("000015", 0, 15, 6); - CheckValidParsedValue(" 123 \t\r\n ", 0, 123, 9); - CheckValidParsedValue("a 5 \r\n ", 1, 5, 7); CheckValidParsedValue(" 987", 0, 987, 4); CheckValidParsedValue("987 ", 0, 987, 4); CheckValidParsedValue("a456", 1, 456, 4); @@ -89,6 +82,11 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("-123", 0); CheckInvalidParsedValue("123456789012345678901234567890", 0); // value >> Int32.MaxValue CheckInvalidParsedValue("2147483648", 0); // value = Int32.MaxValue + 1 + CheckInvalidParsedValue(" 123 \t\r\n ", 0); + CheckInvalidParsedValue("a 5 \r\n ", 1); + CheckInvalidParsedValue("1\n", 0); + CheckInvalidParsedValue("2\r", 0); + CheckInvalidParsedValue("3\r\n ", 0); } [Fact] diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int64NumberHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int64NumberHeaderParserTest.cs index 195917eb89a0e..a76cc6fbd7a1c 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int64NumberHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/Int64NumberHeaderParserTest.cs @@ -1,14 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; + namespace System.Net.Http.Tests { public class Int64NumberHeaderParserTest @@ -60,8 +56,6 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() CheckValidParsedValue("123456789012345", 0, 123456789012345, 15); CheckValidParsedValue("0", 0, 0, 1); CheckValidParsedValue("000015", 0, 15, 6); - CheckValidParsedValue(" 123 \t\r\n ", 0, 123, 9); - CheckValidParsedValue("a 5 \r\n ", 1, 5, 7); CheckValidParsedValue(" 987", 0, 987, 4); CheckValidParsedValue("987 ", 0, 987, 4); CheckValidParsedValue("a456", 1, 456, 4); @@ -88,6 +82,11 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("-123", 0); CheckInvalidParsedValue("123456789012345678901234567890", 0); // value >> Int64.MaxValue CheckInvalidParsedValue("9223372036854775808", 0); // value = Int64.MaxValue + 1 + CheckInvalidParsedValue(" 123 \t\r\n ", 0); + CheckInvalidParsedValue("a 5 \r\n ", 1); + CheckInvalidParsedValue("1\n", 0); + CheckInvalidParsedValue("2\r", 0); + CheckInvalidParsedValue("3\r\n ", 0); } [Fact] diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderParserTest.cs index 85dc002b13b15..f3a0630b29adf 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -62,14 +58,12 @@ public void Parse_NullValue_Throw() public void TryParse_SetOfValidValueStringsForMediaType_ParsedCorrectly() { MediaTypeHeaderValue expected = new MediaTypeHeaderValue("text/plain"); - CheckValidParsedValue("\r\n text/plain ", 0, expected, 15, false); CheckValidParsedValue("text/plain", 0, expected, 10, false); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // media-type parser. expected.CharSet = "utf-8"; - CheckValidParsedValue("\r\n text / plain ; charset = utf-8 ", 0, expected, 40, false); CheckValidParsedValue(" text/plain;charset=utf-8", 2, expected, 26, false); } @@ -77,9 +71,9 @@ public void TryParse_SetOfValidValueStringsForMediaType_ParsedCorrectly() public void TryParse_SetOfValidValueStringsForMediaTypeWithQuality_ParsedCorrectly() { MediaTypeWithQualityHeaderValue expected = new MediaTypeWithQualityHeaderValue("text/plain"); - CheckValidParsedValue("\r\n text/plain ", 0, expected, 15, true); CheckValidParsedValue("text/plain", 0, expected, 10, true); - CheckValidParsedValue("\r\n text/plain , next/mediatype", 0, expected, 17, true); + CheckValidParsedValue("text/plain,", 0, expected, 11, true); + CheckValidParsedValue("text/plain , ", 0, expected, 13, true); CheckValidParsedValue("text/plain, next/mediatype", 0, expected, 12, true); CheckValidParsedValue(" ", 0, null, 2, true); CheckValidParsedValue("", 0, null, 0, true); @@ -90,72 +84,87 @@ public void TryParse_SetOfValidValueStringsForMediaTypeWithQuality_ParsedCorrect // gets called again using the result-index (13), then it fails: I.e. we have 1 valid media-type and an // invalid one. CheckValidParsedValue("text/plain , invalid", 0, expected, 13, true); + CheckValidParsedValue("text/plain , \r\n", 0, expected, 13, true); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // media-type parser. expected.CharSet = "utf-8"; - CheckValidParsedValue("\r\n text / plain ; charset = utf-8 ", 0, expected, 40, true); CheckValidParsedValue(" text/plain;charset=utf-8", 2, expected, 26, true); - CheckValidParsedValue("\r\n text / plain ; charset = utf-8 , next/mediatype", 0, expected, 43, true); + CheckValidParsedValue(" text/plain;charset=utf-8, ", 1, expected, 28, true); CheckValidParsedValue(" text/plain;charset=utf-8, next/mediatype", 2, expected, 28, true); } + [Fact] + public void TryParse_SetOfValidMultiValueStrings_ParsedCorrectly() + { + // Values that are valid for multi, but invalid for single parser + MediaTypeWithQualityHeaderValue expected = null; + Check(""); + Check(" "); + Check(null); + + expected = new MediaTypeWithQualityHeaderValue("text/plain"); + Check("text/plain ,"); + Check("text/plain,"); + + expected.CharSet = "utf-8"; + Check("text/plain; charset=utf-8 ,"); + Check("text/plain; charset=utf-8,"); + + void Check(string input) + { + CheckValidParsedValue(input, 0, expected, expectedIndex: input?.Length ?? 0, supportsMultipleValues: true); + + CheckInvalidParsedValue(input, 0, supportsMultipleValues: false); + } + } + [Fact] public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() { - CheckInvalidParsedValue("", 0, false); - CheckInvalidParsedValue(" ", 0, false); - CheckInvalidParsedValue(null, 0, false); - CheckInvalidParsedValue("text/plain\u4F1A", 0, true); - CheckInvalidParsedValue("text/plain\u4F1A", 0, false); - CheckInvalidParsedValue("text/plain ,", 0, false); - CheckInvalidParsedValue("text/plain,", 0, false); - CheckInvalidParsedValue("text/plain; charset=utf-8 ,", 0, false); - CheckInvalidParsedValue("text/plain; charset=utf-8,", 0, false); - CheckInvalidParsedValue("textplain", 0, true); - CheckInvalidParsedValue("textplain", 0, false); - CheckInvalidParsedValue("text/", 0, true); - CheckInvalidParsedValue("text/", 0, false); + CheckInvalid("text/plain\u4F1A", 0); + CheckInvalid("textplain", 0); + CheckInvalid("text/", 0); + CheckInvalid("\r\n text/plain ", 0); + CheckInvalid("\r\n text / plain ; charset = utf-8 ", 1); + CheckInvalid("\r\n text/plain , next/mediatype", 0); + CheckInvalid(" \r text/plain", 0); + CheckInvalid(" \n text/plain", 0); + CheckInvalid(" \r\n text/plain", 0); + CheckInvalid("text/plain , invalid", 12); + CheckInvalid("text/plain , invalid", 13); + CheckInvalid("text/plain , \r ", 12); + CheckInvalid("text/plain , \n ", 12); + CheckInvalid("text/plain , \r\n ", 12); + CheckInvalid("text/plain , \r\n", 13); + + static void CheckInvalid(string input, int startIndex) + { + CheckInvalidParsedValue(input, startIndex, supportsMultipleValues: true); + CheckInvalidParsedValue(input, startIndex, supportsMultipleValues: false); + } } #region Helper methods - private void CheckValidParsedValue(string input, int startIndex, MediaTypeHeaderValue expectedResult, + private static void CheckValidParsedValue(string input, int startIndex, MediaTypeHeaderValue expectedResult, int expectedIndex, bool supportsMultipleValues) { - MediaTypeHeaderParser parser = null; - if (supportsMultipleValues) - { - parser = MediaTypeHeaderParser.MultipleValuesParser; - } - else - { - parser = MediaTypeHeaderParser.SingleValueParser; - } + MediaTypeHeaderParser parser = supportsMultipleValues ? MediaTypeHeaderParser.MultipleValuesParser : MediaTypeHeaderParser.SingleValueParser; - object result = null; - Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), + Assert.True(parser.TryParseValue(input, null, ref startIndex, out object result), string.Format("TryParse returned false. Input: '{0}', Index: {1}", input, startIndex)); Assert.Equal(expectedIndex, startIndex); Assert.Equal(expectedResult, result); } - private void CheckInvalidParsedValue(string input, int startIndex, bool supportsMultipleValues) + private static void CheckInvalidParsedValue(string input, int startIndex, bool supportsMultipleValues) { - MediaTypeHeaderParser parser = null; - if (supportsMultipleValues) - { - parser = MediaTypeHeaderParser.MultipleValuesParser; - } - else - { - parser = MediaTypeHeaderParser.SingleValueParser; - } + MediaTypeHeaderParser parser = supportsMultipleValues ? MediaTypeHeaderParser.MultipleValuesParser : MediaTypeHeaderParser.SingleValueParser; - object result = null; int newIndex = startIndex; - Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), + Assert.False(parser.TryParseValue(input, null, ref newIndex, out object result), string.Format("TryParse returned true. Input: '{0}', Index: {1}", input, startIndex)); Assert.Null(result); Assert.Equal(startIndex, newIndex); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderValueTest.cs index ed17d1c62a590..88d1a58df0821 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeHeaderValueTest.cs @@ -1,11 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -228,8 +225,8 @@ public void GetMediaTypeLength_DifferentValidScenarios_AllReturnNonZero() Assert.Equal("custom", result.Parameters.ElementAt(0).Name); Assert.Null(result.Parameters.ElementAt(0).Value); - Assert.Equal(48, MediaTypeHeaderValue.GetMediaTypeLength( - "text / plain ; custom =\r\n \"x\" ; charset = utf-8 , next/mediatype", 0, DummyCreator, out result)); + Assert.Equal(46, MediaTypeHeaderValue.GetMediaTypeLength( + "text / plain ; custom = \"x\" ; charset = utf-8 , next/mediatype", 0, DummyCreator, out result)); Assert.Equal("text/plain", result.MediaType); Assert.Equal("utf-8", result.CharSet); Assert.Equal(2, result.Parameters.Count); @@ -295,14 +292,14 @@ public void GetMediaTypeLength_DifferentInvalidScenarios_AllReturnZero() public void Parse_SetOfValidValueStrings_ParsedCorrectly() { MediaTypeHeaderValue expected = new MediaTypeHeaderValue("text/plain"); - CheckValidParse("\r\n text/plain ", expected); + CheckValidParse(" text/plain ", expected); CheckValidParse("text/plain", expected); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // media-type parser. expected.CharSet = "utf-8"; - CheckValidParse("\r\n text / plain ; charset = utf-8 ", expected); + CheckValidParse(" text / plain ; charset = utf-8 ", expected); CheckValidParse(" text/plain;charset=utf-8", expected); } @@ -319,36 +316,9 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse("text/plain; charset=utf-8,"); CheckInvalidParse("textplain"); CheckInvalidParse("text/"); - } - - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - MediaTypeHeaderValue expected = new MediaTypeHeaderValue("text/plain"); - CheckValidTryParse("\r\n text/plain ", expected); - CheckValidTryParse("text/plain", expected); - - // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. - // The purpose of this test is to verify that these other parsers are combined correctly to build a - // media-type parser. - expected.CharSet = "utf-8"; - CheckValidTryParse("\r\n text / plain ; charset = utf-8 ", expected); - CheckValidTryParse(" text/plain;charset=utf-8", expected); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse(""); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(null); - CheckInvalidTryParse("text/plain\u4F1A"); - CheckInvalidTryParse("text/plain ,"); - CheckInvalidTryParse("text/plain,"); - CheckInvalidTryParse("text/plain; charset=utf-8 ,"); - CheckInvalidTryParse("text/plain; charset=utf-8,"); - CheckInvalidTryParse("textplain"); - CheckInvalidTryParse("text/"); + CheckInvalidParse("\r\n text/plain "); + CheckInvalidParse("\r\n text / plain ; charset = utf-8 "); + CheckInvalidParse("text / plain ; custom =\r\n \"x\" ; charset = utf-8 , next/mediatype"); } #region Helper methods @@ -357,24 +327,16 @@ private void CheckValidParse(string input, MediaTypeHeaderValue expectedResult) { MediaTypeHeaderValue result = MediaTypeHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { MediaTypeHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, MediaTypeHeaderValue expectedResult) - { - MediaTypeHeaderValue result = null; Assert.True(MediaTypeHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - MediaTypeHeaderValue result = null; - Assert.False(MediaTypeHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { MediaTypeHeaderValue.Parse(input); }); + + Assert.False(MediaTypeHeaderValue.TryParse(input, out MediaTypeHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeWithQualityHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeWithQualityHeaderValueTest.cs index ad8619b07c9d4..3c119a5cea434 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeWithQualityHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/MediaTypeWithQualityHeaderValueTest.cs @@ -1,11 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -116,14 +113,14 @@ public void Quality_GreaterThanOne_Throw() public void Parse_SetOfValidValueStrings_ParsedCorrectly() { MediaTypeWithQualityHeaderValue expected = new MediaTypeWithQualityHeaderValue("text/plain"); - CheckValidParse("\r\n text/plain ", expected); CheckValidParse("text/plain", expected); + CheckValidParse(" text/plain ", expected); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // media-type parser. expected.CharSet = "utf-8"; - CheckValidParse("\r\n text / plain ; charset = utf-8 ", expected); + CheckValidParse(" text / plain ; charset = utf-8 ", expected); CheckValidParse(" text/plain;charset=utf-8", expected); MediaTypeWithQualityHeaderValue value1 = new MediaTypeWithQualityHeaderValue("text/plain"); @@ -136,7 +133,7 @@ public void Parse_SetOfValidValueStrings_ParsedCorrectly() value2.CharSet = "utf-8"; value2.Quality = 0.5; - CheckValidParse("\r\n */xml; charset=utf-8; q=0.5", value2); + CheckValidParse(" */xml; charset=utf-8; q=0.5", value2); } [Fact] @@ -152,56 +149,20 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse("text/plain; charset=utf-8,"); CheckInvalidParse("textplain"); CheckInvalidParse("text/"); + CheckInvalidParse(",, , ,,text/plain; charset=iso-8859-1; q=1.0, */xml; charset=utf-8; q=0.5,,,"); CheckInvalidParse(",, , ,,text/plain; charset=iso-8859-1; q=1.0,\r\n */xml; charset=utf-8; q=0.5,,,"); CheckInvalidParse("text/plain; charset=iso-8859-1; q=1.0, */xml; charset=utf-8; q=0.5"); CheckInvalidParse(" , */xml; charset=utf-8; q=0.5 "); CheckInvalidParse("text/plain; charset=iso-8859-1; q=1.0 , "); - } - - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - MediaTypeWithQualityHeaderValue expected = new MediaTypeWithQualityHeaderValue("text/plain"); - CheckValidTryParse("\r\n text/plain ", expected); - CheckValidTryParse("text/plain", expected); - - // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. - // The purpose of this test is to verify that these other parsers are combined correctly to build a - // media-type parser. - expected.CharSet = "utf-8"; - CheckValidTryParse("\r\n text / plain ; charset = utf-8 ", expected); - CheckValidTryParse(" text/plain;charset=utf-8", expected); - - MediaTypeWithQualityHeaderValue value1 = new MediaTypeWithQualityHeaderValue("text/plain"); - value1.CharSet = "iso-8859-1"; - value1.Quality = 1.0; - - CheckValidTryParse("text/plain; charset=iso-8859-1; q=1.0", value1); - - MediaTypeWithQualityHeaderValue value2 = new MediaTypeWithQualityHeaderValue("*/xml"); - value2.CharSet = "utf-8"; - value2.Quality = 0.5; - - CheckValidTryParse("\r\n */xml; charset=utf-8; q=0.5", value2); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse(""); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(null); - CheckInvalidTryParse("text/plain\u4F1A"); - CheckInvalidTryParse("text/plain ,"); - CheckInvalidTryParse("text/plain,"); - CheckInvalidTryParse("text/plain; charset=utf-8 ,"); - CheckInvalidTryParse("text/plain; charset=utf-8,"); - CheckInvalidTryParse("textplain"); - CheckInvalidTryParse("text/"); - CheckInvalidTryParse(",, , ,,text/plain; charset=iso-8859-1; q=1.0,\r\n */xml; charset=utf-8; q=0.5,,,"); - CheckInvalidTryParse("text/plain; charset=iso-8859-1; q=1.0, */xml; charset=utf-8; q=0.5"); - CheckInvalidTryParse(" , */xml; charset=utf-8; q=0.5 "); - CheckInvalidTryParse("text/plain; charset=iso-8859-1; q=1.0 , "); + CheckInvalidParse("\r\n */xml; charset=utf-8; q=0.5"); + CheckInvalidParse("text/plain\r"); + CheckInvalidParse("text/plain\n"); + CheckInvalidParse("text/plain\r\n"); + CheckInvalidParse("text/plain\r\n "); + CheckInvalidParse("\r text/plain"); + CheckInvalidParse("\n text/plain"); + CheckInvalidParse("\ntext/plain"); + CheckInvalidParse("\r\n text/plain"); } #region Helper methods @@ -210,22 +171,25 @@ private void CheckValidParse(string input, MediaTypeWithQualityHeaderValue expec { MediaTypeWithQualityHeaderValue result = MediaTypeWithQualityHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { MediaTypeWithQualityHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, MediaTypeWithQualityHeaderValue expectedResult) - { - MediaTypeWithQualityHeaderValue result = null; + result = null; Assert.True(MediaTypeWithQualityHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); + + // New lines are never allowed + for (int i = 0; i < input.Length; i++) + { + CheckInvalidParse(input.Insert(i, "\r")); + CheckInvalidParse(input.Insert(i, "\n")); + CheckInvalidParse(input.Insert(i, "\r\n")); + CheckInvalidParse(input.Insert(i, "\r\n ")); + } } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { + Assert.Throws(() => { MediaTypeWithQualityHeaderValue.Parse(input); }); + MediaTypeWithQualityHeaderValue result = null; Assert.False(MediaTypeWithQualityHeaderValue.TryParse(input, out result)); Assert.Null(result); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueHeaderValueTest.cs index 00ca0d306c9b5..dc2270e545547 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueHeaderValueTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -66,6 +62,8 @@ public void Ctor_NameValidFormat_SuccessfullyCreated(string name, string value) [InlineData("\"quoted string with \"two\" quotes\"")] [InlineData("\"")] [InlineData(" ")] + [InlineData("token\r")] + [InlineData("\"token\r\"")] public void Ctor_ValueInvalidFormat_ThrowFormatException(string value) { // When adding values using strongly typed objects, no leading/trailing LWS (whitespace) are allowed. @@ -308,59 +306,31 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(" ,name=\"value\""); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse(" name = value ", new NameValueHeaderValue("name", "value")); - CheckValidTryParse(" name", new NameValueHeaderValue("name")); - CheckValidTryParse(" name=\"value\"", new NameValueHeaderValue("name", "\"value\"")); - CheckValidTryParse("name=value", new NameValueHeaderValue("name", "value")); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("name[value"); - CheckInvalidTryParse("name=value="); - CheckInvalidTryParse("name=\u4F1A"); - CheckInvalidTryParse("name==value"); - CheckInvalidTryParse("=value"); - CheckInvalidTryParse("name value"); - CheckInvalidTryParse("name=,value"); - CheckInvalidTryParse("\u4F1A"); - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); - CheckInvalidTryParse(" , , name = value , "); - CheckInvalidTryParse(" name,"); - CheckInvalidTryParse(" ,name=\"value\""); - } - #region Helper methods private void CheckValidParse(string input, NameValueHeaderValue expectedResult) { NameValueHeaderValue result = NameValueHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { NameValueHeaderValue.Parse(input); }); - } - - private void CheckValidTryParse(string input, NameValueHeaderValue expectedResult) - { - NameValueHeaderValue result = null; Assert.True(NameValueHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); + + // New lines are never allowed + for (int i = 0; i < input.Length; i++) + { + CheckInvalidParse(input.Insert(i, "\r")); + CheckInvalidParse(input.Insert(i, "\n")); + CheckInvalidParse(input.Insert(i, "\r\n")); + CheckInvalidParse(input.Insert(i, "\r\n ")); + } } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - NameValueHeaderValue result = null; - Assert.False(NameValueHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { NameValueHeaderValue.Parse(input); }); + + Assert.False(NameValueHeaderValue.TryParse(input, out NameValueHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueWithParametersHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueWithParametersHeaderValueTest.cs index a197441961125..5aca687e2882e 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueWithParametersHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/NameValueWithParametersHeaderValueTest.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Linq; using System.Net.Http.Headers; @@ -192,21 +191,25 @@ public void GetNameValueLength_DifferentInvalidScenarios_AllReturnZero() public void Parse_SetOfValidValueStrings_ParsedCorrectly() { NameValueWithParametersHeaderValue expected = new NameValueWithParametersHeaderValue("custom"); - CheckValidParse("\r\n custom ", expected); + CheckValidParse(" custom ", expected); CheckValidParse("custom", expected); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // transfer-coding parser. expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidParse("\r\n custom ; name = value ", expected); + CheckValidParse(" custom ; name = value ", expected); CheckValidParse(" custom;name=value", expected); CheckValidParse(" custom ; name=value", expected); + + expected.Parameters.Add(new NameValueHeaderValue("foo", "bar")); + CheckValidParse("custom; name=value; foo=bar", expected); } [Fact] public void Parse_SetOfInvalidValueStrings_Throws() { + CheckInvalidParse("custom\n"); CheckInvalidParse("custom\u4F1A"); CheckInvalidParse("custom; name=value;"); CheckInvalidParse("custom; name1=value1; name2=value2;"); @@ -216,58 +219,31 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(" ,,"); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - NameValueWithParametersHeaderValue expected = new NameValueWithParametersHeaderValue("custom"); - CheckValidTryParse("\r\n custom ", expected); - CheckValidTryParse("custom", expected); - - // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. - // The purpose of this test is to verify that these other parsers are combined correctly to build a - // transfer-coding parser. - expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidTryParse("\r\n custom ; name = value ", expected); - CheckValidTryParse(" custom;name=value", expected); - CheckValidTryParse(" custom ; name=value", expected); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("custom\u4F1A"); - CheckInvalidTryParse("custom; name=value;"); - CheckInvalidTryParse("custom; name1=value1; name2=value2;"); - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); - } - #region Helper methods private void CheckValidParse(string input, NameValueWithParametersHeaderValue expectedResult) { NameValueWithParametersHeaderValue result = NameValueWithParametersHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { NameValueWithParametersHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, NameValueWithParametersHeaderValue expectedResult) - { - NameValueWithParametersHeaderValue result = null; Assert.True(NameValueWithParametersHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); + + // New lines are never allowed + for (int i = 0; i < input.Length; i++) + { + CheckInvalidParse(input.Insert(i, "\r")); + CheckInvalidParse(input.Insert(i, "\n")); + CheckInvalidParse(input.Insert(i, "\r\n")); + CheckInvalidParse(input.Insert(i, "\r\n ")); + } } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - NameValueWithParametersHeaderValue result = null; - Assert.False(NameValueWithParametersHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { NameValueWithParametersHeaderValue.Parse(input); }); + + Assert.False(NameValueWithParametersHeaderValue.TryParse(input, out NameValueWithParametersHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductHeaderValueTest.cs index eeea82490b6ed..e810e572f07cb 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductHeaderValueTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -166,53 +162,22 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(" ,,"); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse(" y/1 ", new ProductHeaderValue("y", "1")); - CheckValidTryParse(" custom / 1.0 ", new ProductHeaderValue("custom", "1.0")); - CheckValidTryParse("custom / 1.0 ", new ProductHeaderValue("custom", "1.0")); - CheckValidTryParse("custom / 1.0", new ProductHeaderValue("custom", "1.0")); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("product/version="); // only delimiter ',' allowed after last product - CheckInvalidTryParse("product otherproduct"); - CheckInvalidTryParse("product["); - CheckInvalidTryParse("="); - - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); - } - #region Helper methods private void CheckValidParse(string input, ProductHeaderValue expectedResult) { ProductHeaderValue result = ProductHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { ProductHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, ProductHeaderValue expectedResult) - { - ProductHeaderValue result = null; Assert.True(ProductHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - ProductHeaderValue result = null; - Assert.False(ProductHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { ProductHeaderValue.Parse(input); }); + + Assert.False(ProductHeaderValue.TryParse(input, out ProductHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderParserTest.cs index b6311144a31ba..83bb6fa873a5c 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderValueTest.cs index c6b716f816750..59cacbb496d0d 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ProductInfoHeaderValueTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -189,61 +185,22 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse("\t"); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse("product", new ProductInfoHeaderValue("product", null)); - CheckValidTryParse(" product ", new ProductInfoHeaderValue("product", null)); - - CheckValidTryParse(" (comment) ", new ProductInfoHeaderValue("(comment)")); - - CheckValidTryParse(" Mozilla/5.0 ", new ProductInfoHeaderValue("Mozilla", "5.0")); - CheckValidTryParse(" (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) ", - new ProductInfoHeaderValue("(compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)")); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("p/1.0,"); - CheckInvalidTryParse("p/1.0\r\n"); // for \r\n to be a valid whitespace, it must be followed by space/tab - CheckInvalidTryParse("p/1.0(comment)"); - CheckInvalidTryParse("(comment)["); - - CheckInvalidTryParse(" Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) "); - CheckInvalidTryParse("p/1.0 ="); - - // "User-Agent" and "Server" don't allow empty values (unlike most other headers supporting lists of values) - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse("\t"); - } - #region Helper methods private void CheckValidParse(string input, ProductInfoHeaderValue expectedResult) { ProductInfoHeaderValue result = ProductInfoHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { ProductInfoHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, ProductInfoHeaderValue expectedResult) - { - ProductInfoHeaderValue result = null; Assert.True(ProductInfoHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - ProductInfoHeaderValue result = null; - Assert.False(ProductInfoHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { ProductInfoHeaderValue.Parse(input); }); + + Assert.False(ProductInfoHeaderValue.TryParse(input, out ProductInfoHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeConditionHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeConditionHeaderValueTest.cs index 87182e95da854..edb31cbe1584d 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeConditionHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeConditionHeaderValueTest.cs @@ -169,49 +169,22 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(string.Empty); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse(" \"x\" ", new RangeConditionHeaderValue("\"x\"")); - CheckValidTryParse(" Sun, 06 Nov 1994 08:49:37 GMT ", - new RangeConditionHeaderValue(new DateTimeOffset(1994, 11, 6, 8, 49, 37, TimeSpan.Zero))); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("\"x\" ,"); // no delimiter allowed - CheckInvalidTryParse("Sun, 06 Nov 1994 08:49:37 GMT ,"); // no delimiter allowed - CheckInvalidTryParse("\"x\" Sun, 06 Nov 1994 08:49:37 GMT"); - CheckInvalidTryParse("Sun, 06 Nov 1994 08:49:37 GMT \"x\""); - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - } - #region Helper methods private void CheckValidParse(string input, RangeConditionHeaderValue expectedResult) { RangeConditionHeaderValue result = RangeConditionHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { RangeConditionHeaderValue.Parse(input); }); - } - - private void CheckValidTryParse(string input, RangeConditionHeaderValue expectedResult) - { - RangeConditionHeaderValue result = null; Assert.True(RangeConditionHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - RangeConditionHeaderValue result = null; - Assert.False(RangeConditionHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { RangeConditionHeaderValue.Parse(input); }); + + Assert.False(RangeConditionHeaderValue.TryParse(input, out RangeConditionHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeHeaderValueTest.cs index ee4a8ef18694c..463a6fdac95c9 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/RangeHeaderValueTest.cs @@ -170,52 +170,22 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(string.Empty); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse(" bytes=1-2 ", new RangeHeaderValue(1, 2)); - - RangeHeaderValue expected = new RangeHeaderValue(); - expected.Unit = "custom"; - expected.Ranges.Add(new RangeItemHeaderValue(null, 5)); - expected.Ranges.Add(new RangeItemHeaderValue(1, 4)); - CheckValidTryParse("custom = - 5 , 1 - 4 ,,", expected); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("bytes=1-2x"); // only delimiter ',' allowed after last range - CheckInvalidTryParse("x bytes=1-2"); - CheckInvalidTryParse("bytes=1-2.4"); - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - } - #region Helper methods private void CheckValidParse(string input, RangeHeaderValue expectedResult) { RangeHeaderValue result = RangeHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { RangeHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, RangeHeaderValue expectedResult) - { - RangeHeaderValue result = null; Assert.True(RangeHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - RangeHeaderValue result = null; - Assert.False(RangeHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { RangeHeaderValue.Parse(input); }); + + Assert.False(RangeHeaderValue.TryParse(input, out RangeHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/RetryConditionHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/RetryConditionHeaderValueTest.cs index 7ac59bfc93d23..e110666a6b890 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/RetryConditionHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/RetryConditionHeaderValueTest.cs @@ -143,6 +143,8 @@ public void GetRetryConditionLength_DifferentInvalidScenarios_AllReturnZero() CheckInvalidGetRetryConditionLength("", 0); CheckInvalidGetRetryConditionLength(null, 0); + + CheckInvalidGetRetryConditionLength(" 1234567890\n ", 0); } [Fact] @@ -164,49 +166,22 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(string.Empty); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse(" 123456789 ", new RetryConditionHeaderValue(new TimeSpan(0, 0, 123456789))); - CheckValidTryParse(" Sun, 06 Nov 1994 08:49:37 GMT ", - new RetryConditionHeaderValue(new DateTimeOffset(1994, 11, 6, 8, 49, 37, TimeSpan.Zero))); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("123 ,"); // no delimiter allowed - CheckInvalidTryParse("Sun, 06 Nov 1994 08:49:37 GMT ,"); // no delimiter allowed - CheckInvalidTryParse("123 Sun, 06 Nov 1994 08:49:37 GMT"); - CheckInvalidTryParse("Sun, 06 Nov 1994 08:49:37 GMT \"x\""); - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - } - #region Helper methods private void CheckValidParse(string input, RetryConditionHeaderValue expectedResult) { RetryConditionHeaderValue result = RetryConditionHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { RetryConditionHeaderValue.Parse(input); }); - } - - private void CheckValidTryParse(string input, RetryConditionHeaderValue expectedResult) - { - RetryConditionHeaderValue result = null; Assert.True(RetryConditionHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - RetryConditionHeaderValue result = null; - Assert.False(RetryConditionHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { RetryConditionHeaderValue.Parse(input); }); + + Assert.False(RetryConditionHeaderValue.TryParse(input, out RetryConditionHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/StringWithQualityHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/StringWithQualityHeaderValueTest.cs index 54cf08c97a832..8e3075c10168b 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/StringWithQualityHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/StringWithQualityHeaderValueTest.cs @@ -176,9 +176,9 @@ public void Parse_SetOfValidValueStrings_ParsedCorrectly() CheckValidParse("text", new StringWithQualityHeaderValue("text")); CheckValidParse("text;q=0.5", new StringWithQualityHeaderValue("text", 0.5)); CheckValidParse("text ; q = 0.5", new StringWithQualityHeaderValue("text", 0.5)); - CheckValidParse("\r\n text ; q = 0.5 ", new StringWithQualityHeaderValue("text", 0.5)); + CheckValidParse(" text ; q = 0.5 ", new StringWithQualityHeaderValue("text", 0.5)); CheckValidParse(" text ", new StringWithQualityHeaderValue("text")); - CheckValidParse(" \r\n text \r\n ; \r\n q = 0.123", new StringWithQualityHeaderValue("text", 0.123)); + CheckValidParse(" text ; q = 0.123", new StringWithQualityHeaderValue("text", 0.123)); } [Fact] @@ -207,67 +207,31 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(" ,,"); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse("text", new StringWithQualityHeaderValue("text")); - CheckValidTryParse("text;q=0.5", new StringWithQualityHeaderValue("text", 0.5)); - CheckValidTryParse("text ; q = 0.5", new StringWithQualityHeaderValue("text", 0.5)); - CheckValidTryParse("\r\n text ; q = 0.5 ", new StringWithQualityHeaderValue("text", 0.5)); - CheckValidTryParse(" text ", new StringWithQualityHeaderValue("text")); - CheckValidTryParse(" \r\n text \r\n ; \r\n q = 0.123", new StringWithQualityHeaderValue("text", 0.123)); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("text,"); - CheckInvalidTryParse("\r\n text ; q = 0.5, next_text "); - CheckInvalidTryParse(" text,next_text "); - CheckInvalidTryParse(" ,, text, , ,next"); - CheckInvalidTryParse(" ,, text, , ,"); - CheckInvalidTryParse(", \r\n text \r\n ; \r\n q = 0.123"); - CheckInvalidTryParse("te\u00E4xt"); - CheckInvalidTryParse("text\u4F1A"); - CheckInvalidTryParse("\u4F1A"); - CheckInvalidTryParse("t;q=\u4F1A"); - CheckInvalidTryParse("t;q="); - CheckInvalidTryParse("t;q"); - CheckInvalidTryParse("t;\u4F1A=1"); - CheckInvalidTryParse("t;q\u4F1A=1"); - CheckInvalidTryParse("t y"); - CheckInvalidTryParse("t;q=1 y"); - - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); - } - #region Helper methods private void CheckValidParse(string input, StringWithQualityHeaderValue expectedResult) { StringWithQualityHeaderValue result = StringWithQualityHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { StringWithQualityHeaderValue.Parse(input); }); - } - - private void CheckValidTryParse(string input, StringWithQualityHeaderValue expectedResult) - { - StringWithQualityHeaderValue result = null; Assert.True(StringWithQualityHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); + + // New lines are never allowed + for (int i = 0; i < input.Length; i++) + { + CheckInvalidParse(input.Insert(i, "\r")); + CheckInvalidParse(input.Insert(i, "\n")); + CheckInvalidParse(input.Insert(i, "\r\n")); + CheckInvalidParse(input.Insert(i, "\r\n ")); + } } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - StringWithQualityHeaderValue result = null; - Assert.False(StringWithQualityHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { StringWithQualityHeaderValue.Parse(input); }); + + Assert.False(StringWithQualityHeaderValue.TryParse(input, out StringWithQualityHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TimeSpanHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TimeSpanHeaderParserTest.cs index 12894aa9a7930..fc59f80efcf01 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TimeSpanHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TimeSpanHeaderParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -60,8 +56,8 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() CheckValidParsedValue("1234567890", 0, new TimeSpan(0, 0, 1234567890), 10); CheckValidParsedValue("0", 0, new TimeSpan(0, 0, 0), 1); CheckValidParsedValue("000015", 0, new TimeSpan(0, 0, 15), 6); - CheckValidParsedValue(" 123 \t\r\n ", 0, new TimeSpan(0, 0, 123), 9); - CheckValidParsedValue("a 5 \r\n ", 1, new TimeSpan(0, 0, 5), 7); + CheckValidParsedValue(" 123 \t ", 0, new TimeSpan(0, 0, 123), 7); + CheckValidParsedValue("a 5 ", 1, new TimeSpan(0, 0, 5), 5); CheckValidParsedValue(" 987", 0, new TimeSpan(0, 0, 987), 4); CheckValidParsedValue("987 ", 0, new TimeSpan(0, 0, 987), 4); CheckValidParsedValue("a456", 1, new TimeSpan(0, 0, 456), 4); @@ -88,6 +84,8 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() CheckInvalidParsedValue("-123", 0); CheckInvalidParsedValue("123456789012345678901234567890", 0); // value >> Int32.MaxValue CheckInvalidParsedValue("2147483648", 0); // value = Int32.MaxValue + 1 + CheckInvalidParsedValue(" 123 \t\r\n", 0); + CheckInvalidParsedValue("a 5 \r\n ", 0); } [Fact] diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderParserTest.cs index a113f5f4a9270..79b27b8cec10c 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderParserTest.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -60,12 +56,12 @@ public void Parse_InvalidValue_Throw() public void TryParse_SetOfValidValueStrings_ParsedCorrectly() { TransferCodingHeaderValue expected = new TransferCodingHeaderValue("custom"); - CheckValidParsedValue("\r\n custom ", 0, expected, 11); + CheckValidParsedValue(" custom ", 0, expected, 9); CheckValidParsedValue("custom", 0, expected, 6); CheckValidParsedValue(",,custom", 0, expected, 8); CheckValidParsedValue(" , , custom", 0, expected, 11); - CheckValidParsedValue("\r\n custom , chunked", 0, expected, 13); - CheckValidParsedValue("\r\n custom , , , chunked", 0, expected, 17); + CheckValidParsedValue(" custom , chunked", 0, expected, 11); + CheckValidParsedValue(" custom , , , chunked", 0, expected, 15); CheckValidParsedValue(null, 0, null, 0); CheckValidParsedValue(string.Empty, 0, null, 0); @@ -81,8 +77,8 @@ public void TryParse_SetOfValidValueStrings_ParsedCorrectly() // The purpose of this test is to verify that these other parsers are combined correctly to build a // transfer-coding parser. expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidParsedValue("\r\n custom ; name = value ", 0, expected, 28); - CheckValidParsedValue("\r\n , , custom ; name = value ", 0, expected, 32); + CheckValidParsedValue(" custom ; name = value ", 0, expected, 26); + CheckValidParsedValue(" , , custom ; name = value ", 0, expected, 30); CheckValidParsedValue(" custom;name=value", 2, expected, 19); CheckValidParsedValue(" custom ; name=value", 2, expected, 21); } @@ -92,6 +88,8 @@ public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() { CheckInvalidParsedValue("custom; name=value;", 0); CheckInvalidParsedValue("custom; name1=value1; name2=value2;", 0); + CheckInvalidParsedValue("custom; \r\n name=value;", 0); + CheckInvalidParsedValue("custom; name1=value1; name2=value2;\r\n", 0); } #region Helper methods diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderValueTest.cs index 5982b6d0c0b14..e59958ea42103 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingHeaderValueTest.cs @@ -1,11 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -171,8 +168,8 @@ public void GetTransferCodingLength_DifferentValidScenarios_AllReturnNonZero() // of 0. The caller needs to validate if that's OK or not. Assert.Equal(0, TransferCodingHeaderValue.GetTransferCodingLength("\u4F1A", 0, DummyCreator, out result)); - Assert.Equal(45, TransferCodingHeaderValue.GetTransferCodingLength( - " custom ; name1 =\r\n \"value1\" ; name2 = value2 , next", 2, DummyCreator, out result)); + Assert.Equal(43, TransferCodingHeaderValue.GetTransferCodingLength( + " custom ; name1 = \"value1\" ; name2 = value2 , next", 2, DummyCreator, out result)); Assert.Equal("custom", result.Value); Assert.Equal(2, result.Parameters.Count); Assert.Equal("name1", result.Parameters.ElementAt(0).Name); @@ -218,20 +215,23 @@ public void GetTransferCodingLength_DifferentInvalidScenarios_AllReturnZero() Assert.Equal(0, TransferCodingHeaderValue.GetTransferCodingLength(string.Empty, 0, DummyCreator, out result)); Assert.Null(result); + Assert.Equal(0, TransferCodingHeaderValue.GetTransferCodingLength("\r\nchunked", 0, DummyCreator, + out result)); + Assert.Null(result); } [Fact] public void Parse_SetOfValidValueStrings_ParsedCorrectly() { TransferCodingHeaderValue expected = new TransferCodingHeaderValue("custom"); - CheckValidParse("\r\n custom ", expected); + CheckValidParse(" custom ", expected); CheckValidParse("custom", expected); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // transfer-coding parser. expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidParse("\r\n custom ; name = value ", expected); + CheckValidParse(" custom ; name = value ", expected); CheckValidParse(" custom;name=value", expected); CheckValidParse(" custom ; name=value", expected); } @@ -247,6 +247,7 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse("\r\n custom , , , chunked"); CheckInvalidParse("custom , \u4F1A"); CheckInvalidParse("\r\n , , custom ; name = value "); + CheckInvalidParse(" custom ; \r\n name = value "); CheckInvalidParse(null); CheckInvalidParse(string.Empty); @@ -254,64 +255,22 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(" ,,"); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - TransferCodingHeaderValue expected = new TransferCodingHeaderValue("custom"); - CheckValidTryParse("\r\n custom ", expected); - CheckValidTryParse("custom", expected); - - // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. - // The purpose of this test is to verify that these other parsers are combined correctly to build a - // transfer-coding parser. - expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidTryParse("\r\n custom ; name = value ", expected); - CheckValidTryParse(" custom;name=value", expected); - CheckValidTryParse(" custom ; name=value", expected); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("custom; name=value;"); - CheckInvalidTryParse("custom; name1=value1; name2=value2;"); - CheckInvalidTryParse(",,custom"); - CheckInvalidTryParse(" , , custom"); - CheckInvalidTryParse("\r\n custom , chunked"); - CheckInvalidTryParse("\r\n custom , , , chunked"); - CheckInvalidTryParse("custom , \u4F1A"); - CheckInvalidTryParse("\r\n , , custom ; name = value "); - - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); - } - #region Helper methods private void CheckValidParse(string input, TransferCodingHeaderValue expectedResult) { TransferCodingHeaderValue result = TransferCodingHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { TransferCodingHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, TransferCodingHeaderValue expectedResult) - { - TransferCodingHeaderValue result = null; Assert.True(TransferCodingHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - TransferCodingHeaderValue result = null; - Assert.False(TransferCodingHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { TransferCodingHeaderValue.Parse(input); }); + + Assert.False(TransferCodingHeaderValue.TryParse(input, out TransferCodingHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingWithQualityHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingWithQualityHeaderValueTest.cs index 0080a3e2ef0e3..2e36f6b25445d 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingWithQualityHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/TransferCodingWithQualityHeaderValueTest.cs @@ -1,11 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; -using System.Text; using Xunit; @@ -51,14 +48,14 @@ public void Ctor_AddValueAndQuality_QualityParameterAdded() public void Parse_SetOfValidValueStrings_ParsedCorrectly() { TransferCodingWithQualityHeaderValue expected = new TransferCodingWithQualityHeaderValue("custom"); - CheckValidParse("\r\n custom ", expected); + CheckValidParse(" custom ", expected); CheckValidParse("custom", expected); // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. // The purpose of this test is to verify that these other parsers are combined correctly to build a // transfer-coding parser. expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidParse("\r\n custom ; name = value ", expected); + CheckValidParse(" custom ; name = value ", expected); CheckValidParse(" custom;name=value", expected); CheckValidParse(" custom ; name=value", expected); @@ -73,7 +70,7 @@ public void Parse_SetOfValidValueStrings_ParsedCorrectly() value2.Parameters.Add(new NameValueHeaderValue("param2", "value2")); value2.Quality = 0.5; - CheckValidParse("\r\n custom2; param2= value2; q =0.5 ", value2); + CheckValidParse(" custom2; param2= value2; q =0.5 ", value2); } [Fact] @@ -91,6 +88,7 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(",custom1; param1=value1; q=1.0,,\r\n custom2; param2=value2; q=0.5 ,"); CheckInvalidParse("custom1; param1=value1; q=1.0,"); CheckInvalidParse(",\r\n custom2; param2=value2; q=0.5"); + CheckInvalidParse("\r\n custom2; param2= value2; q =0.5 "); CheckInvalidParse(null); CheckInvalidParse(string.Empty); @@ -98,83 +96,25 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(" ,,"); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - TransferCodingWithQualityHeaderValue expected = new TransferCodingWithQualityHeaderValue("custom"); - CheckValidTryParse("\r\n custom ", expected); - CheckValidTryParse("custom", expected); - - // We don't have to test all possible input strings, since most of the pieces are handled by other parsers. - // The purpose of this test is to verify that these other parsers are combined correctly to build a - // transfer-coding parser. - expected.Parameters.Add(new NameValueHeaderValue("name", "value")); - CheckValidTryParse("\r\n custom ; name = value ", expected); - CheckValidTryParse(" custom;name=value", expected); - CheckValidTryParse(" custom ; name=value", expected); - - - TransferCodingWithQualityHeaderValue value1 = new TransferCodingWithQualityHeaderValue("custom1"); - value1.Parameters.Add(new NameValueHeaderValue("param1", "value1")); - value1.Quality = 1.0; - - CheckValidTryParse("custom1 ; param1 =value1 ; q= 1.0 ", value1); - - TransferCodingWithQualityHeaderValue value2 = new TransferCodingWithQualityHeaderValue("custom2"); - value2.Parameters.Add(new NameValueHeaderValue("param2", "value2")); - value2.Quality = 0.5; - - CheckValidTryParse("\r\n custom2; param2= value2; q =0.5 ", value2); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("custom; name=value;"); - CheckInvalidTryParse("custom; name1=value1; name2=value2;"); - CheckInvalidTryParse(",,custom"); - CheckInvalidTryParse(" , , custom"); - CheckInvalidTryParse("\r\n custom , chunked"); - CheckInvalidTryParse("\r\n custom , , , chunked"); - CheckInvalidTryParse("custom , \u4F1A"); - CheckInvalidTryParse("\r\n , , custom ; name = value "); - - CheckInvalidTryParse(",custom1; param1=value1; q=1.0,,\r\n custom2; param2=value2; q=0.5 ,"); - CheckInvalidTryParse("custom1; param1=value1; q=1.0,"); - CheckInvalidTryParse(",\r\n custom2; param2=value2; q=0.5"); - - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); - } - #region Helper methods private void CheckValidParse(string input, TransferCodingWithQualityHeaderValue expectedResult) { TransferCodingWithQualityHeaderValue result = TransferCodingWithQualityHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { TransferCodingWithQualityHeaderValue.Parse(input); }); - } - private void CheckValidTryParse(string input, TransferCodingWithQualityHeaderValue expectedResult) - { - TransferCodingWithQualityHeaderValue result = null; Assert.True(TransferCodingWithQualityHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - TransferCodingWithQualityHeaderValue result = null; - Assert.False(TransferCodingWithQualityHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { TransferCodingWithQualityHeaderValue.Parse(input); }); + + Assert.False(TransferCodingWithQualityHeaderValue.TryParse(input, out TransferCodingWithQualityHeaderValue result)); Assert.Null(result); } + #endregion } } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ViaHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ViaHeaderValueTest.cs index 5662201a6a08f..902a5fd5ac3ec 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ViaHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ViaHeaderValueTest.cs @@ -229,7 +229,7 @@ public void GetViaLength_DifferentInvalidScenarios_AllReturnZero() public void Parse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidParse(" 1.1 host ", new ViaHeaderValue("1.1", "host")); - CheckValidParse(" HTTP / x11 192.168.0.1\r\n (comment) ", + CheckValidParse(" HTTP / x11 192.168.0.1 (comment) ", new ViaHeaderValue("x11", "192.168.0.1", "HTTP", "(comment)")); CheckValidParse(" HTTP/1.1 [::1]", new ViaHeaderValue("1.1", "[::1]", "HTTP")); CheckValidParse("1.1 host", new ViaHeaderValue("1.1", "host")); @@ -258,41 +258,7 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(string.Empty); CheckInvalidParse(" "); CheckInvalidParse(" ,,"); - } - - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse(" 1.1 host ", new ViaHeaderValue("1.1", "host")); - CheckValidTryParse(" HTTP / x11 192.168.0.1\r\n (comment) ", - new ViaHeaderValue("x11", "192.168.0.1", "HTTP", "(comment)")); - CheckValidTryParse(" HTTP/1.1 [::1]", new ViaHeaderValue("1.1", "[::1]", "HTTP")); - CheckValidTryParse("1.1 host", new ViaHeaderValue("1.1", "host")); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("HTTP/1.1 host (comment)invalid"); - CheckInvalidTryParse("HTTP/1.1 host (comment)="); - CheckInvalidTryParse("HTTP/1.1 host (comment) invalid"); - CheckInvalidTryParse("HTTP/1.1 host (comment) ="); - CheckInvalidTryParse("HTTP/1.1 host invalid"); - CheckInvalidTryParse("HTTP/1.1 host ="); - CheckInvalidTryParse("1.1 host invalid"); - CheckInvalidTryParse("1.1 host ="); - CheckInvalidTryParse("\u4F1A"); - CheckInvalidTryParse("HTTP/test [::1]:80\r(comment)"); - CheckInvalidTryParse("HTTP/test [::1]:80\n(comment)"); - - CheckInvalidTryParse("X , , 1.1 host, ,next"); - CheckInvalidTryParse("X HTTP / x11 192.168.0.1\r\n (comment) , ,next"); - CheckInvalidTryParse(" ,HTTP/1.1 [::1]"); - - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); + CheckInvalidParse("1=host\n"); } #region Helper methods @@ -301,24 +267,16 @@ private void CheckValidParse(string input, ViaHeaderValue expectedResult) { ViaHeaderValue result = ViaHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { ViaHeaderValue.Parse(input); }); - } - - private void CheckValidTryParse(string input, ViaHeaderValue expectedResult) - { - ViaHeaderValue result = null; Assert.True(ViaHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - ViaHeaderValue result = null; - Assert.False(ViaHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { ViaHeaderValue.Parse(input); }); + + Assert.False(ViaHeaderValue.TryParse(input, out ViaHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/WarningHeaderValueTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/WarningHeaderValueTest.cs index 14cafddc08b4f..dc867577ea76e 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/WarningHeaderValueTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/WarningHeaderValueTest.cs @@ -147,7 +147,7 @@ public void Clone_Call_CloneFieldsMatchSourceFields() [Fact] public void GetWarningLength_DifferentValidScenarios_AllReturnNonZero() { - CheckGetWarningLength(" 199 .host \r\n \"Miscellaneous warning\" ", 1, 38, + CheckGetWarningLength(" 199 .host \"Miscellaneous warning\" ", 1, 35, new WarningHeaderValue(199, ".host", "\"Miscellaneous warning\"")); CheckGetWarningLength("987 [FE18:AB64::156]:80 \"\" \"Tue, 20 Jul 2010 01:02:03 GMT\"", 0, 58, new WarningHeaderValue(987, "[FE18:AB64::156]:80", "\"\"", @@ -196,6 +196,8 @@ public void GetWarningLength_DifferentInvalidScenarios_AllReturnZero() CheckInvalidWarningViaLength("123 host \"t\" \"Tue, 20 Jul 2010 01:02:03 GMT", 0); CheckInvalidWarningViaLength("123 host \"t\" \"Tue, 200 Jul 2010 01:02:03 GMT\"", 0); CheckInvalidWarningViaLength("123 host \"t\" \"\"", 0); + + CheckInvalidWarningViaLength(" 199 .host \r\n \"Miscellaneous warning\" \r\n ", 0); } [Fact] @@ -236,68 +238,22 @@ public void Parse_SetOfInvalidValueStrings_Throws() CheckInvalidParse(" ,,"); } - [Fact] - public void TryParse_SetOfValidValueStrings_ParsedCorrectly() - { - CheckValidTryParse(" 123 host \"text\"", new WarningHeaderValue(123, "host", "\"text\"")); - CheckValidTryParse(" 50 192.168.0.1 \"text \" \"Tue, 20 Jul 2010 01:02:03 GMT\" ", - new WarningHeaderValue(50, "192.168.0.1", "\"text \"", - new DateTimeOffset(2010, 7, 20, 1, 2, 3, TimeSpan.Zero))); - CheckValidTryParse(" 123 h \"t\"", new WarningHeaderValue(123, "h", "\"t\"")); - CheckValidTryParse("1 h \"t\"", new WarningHeaderValue(1, "h", "\"t\"")); - CheckValidTryParse("1 h \"t\" \"Tue, 20 Jul 2010 01:02:03 GMT\"", - new WarningHeaderValue(1, "h", "\"t\"", - new DateTimeOffset(2010, 7, 20, 1, 2, 3, TimeSpan.Zero))); - CheckValidTryParse("1 \u4F1A \"t\" ", new WarningHeaderValue(1, "\u4F1A", "\"t\"")); - } - - [Fact] - public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() - { - CheckInvalidTryParse("1.1 host \"text\""); - CheckInvalidTryParse("11 host text"); - CheckInvalidTryParse("11 host \"text\" Tue, 20 Jul 2010 01:02:03 GMT"); - CheckInvalidTryParse("11 host \"text\" 123 next \"text\""); - CheckInvalidTryParse("\u4F1A"); - CheckInvalidTryParse("123 \u4F1A"); - CheckInvalidTryParse("111 [::1]:80\r(comment) \"text\""); - CheckInvalidTryParse("111 [::1]:80\n(comment) \"text\""); - - CheckInvalidTryParse("X , , 123 host \"text\", ,next"); - CheckInvalidTryParse("X 50 192.168.0.1 \"text \" \"Tue, 20 Jul 2010 01:02:03 GMT\" , ,next"); - CheckInvalidTryParse(" ,123 h \"t\","); - CheckInvalidTryParse("1 \u4F1A \"t\" ,,"); - - CheckInvalidTryParse(null); - CheckInvalidTryParse(string.Empty); - CheckInvalidTryParse(" "); - CheckInvalidTryParse(" ,,"); - } - #region Helper methods private void CheckValidParse(string input, WarningHeaderValue expectedResult) { WarningHeaderValue result = WarningHeaderValue.Parse(input); Assert.Equal(expectedResult, result); - } - private void CheckInvalidParse(string input) - { - Assert.Throws(() => { WarningHeaderValue.Parse(input); }); - } - - private void CheckValidTryParse(string input, WarningHeaderValue expectedResult) - { - WarningHeaderValue result = null; Assert.True(WarningHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } - private void CheckInvalidTryParse(string input) + private void CheckInvalidParse(string input) { - WarningHeaderValue result = null; - Assert.False(WarningHeaderValue.TryParse(input, out result)); + Assert.Throws(() => { WarningHeaderValue.Parse(input); }); + + Assert.False(WarningHeaderValue.TryParse(input, out WarningHeaderValue result)); Assert.Null(result); } diff --git a/src/libraries/System.Net.Http/tests/UnitTests/HttpRuleParserTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/HttpRuleParserTest.cs index 1f0bac6489266..707ddae2f4658 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/HttpRuleParserTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/HttpRuleParserTest.cs @@ -189,7 +189,6 @@ public void GetQuotedStringLength_SetOfValidQuotedStrings_AllConsideredValid() AssertGetQuotedStringLength("\"\\xx\"", 0, 5, HttpParseResult.Parsed); // "\xx" AssertGetQuotedStringLength("\"(x)\"", 0, 5, HttpParseResult.Parsed); // "(x)" AssertGetQuotedStringLength(" \" (x) \" ", 1, 7, HttpParseResult.Parsed); // " (x) " - AssertGetQuotedStringLength("\"text\r\n new line\"", 0, 17, HttpParseResult.Parsed); // "text new line" AssertGetQuotedStringLength("\"a\\\u00FC\\\"b\\\"c\\\"\\\"d\\\"\"", 0, 18, HttpParseResult.Parsed); // "a\\u00FC\"b\"c\"\"d\"" AssertGetQuotedStringLength("\"\\\" \"", 0, 5, HttpParseResult.Parsed); // "\" " } @@ -199,6 +198,7 @@ public void GetQuotedStringLength_SetOfInvalidQuotedStrings_AllConsideredInvalid { AssertGetQuotedStringLength("\"x", 0, 0, HttpParseResult.InvalidFormat); // "x AssertGetQuotedStringLength(" \"x ", 1, 0, HttpParseResult.InvalidFormat); // ' "x ' + AssertGetQuotedStringLength("\"text\r\n new line\"", 0, 0, HttpParseResult.InvalidFormat); // "text new line" } [Fact] @@ -224,7 +224,6 @@ public void GetCommentLength_SetOfValidComments_AllConsideredValid() AssertGetCommentLength("(\\xx)", 0, 5, HttpParseResult.Parsed); // (\xx) AssertGetCommentLength("(\"x\")", 0, 5, HttpParseResult.Parsed); // ("x") AssertGetCommentLength(" ( \"x\" ) ", 1, 7, HttpParseResult.Parsed); // ( "x" ) - AssertGetCommentLength("(text\r\n new line)", 0, 17, HttpParseResult.Parsed); // (text new line) AssertGetCommentLength("(\\) )", 0, 5, HttpParseResult.Parsed); // (\)) AssertGetCommentLength("(\\( )", 0, 5, HttpParseResult.Parsed); // (\() @@ -253,6 +252,7 @@ public void GetCommentLength_SetOfInvalidQuotedStrings_AllConsideredInvalid() AssertGetCommentLength("((x ", 0, 0, HttpParseResult.InvalidFormat); AssertGetCommentLength("(x(x ", 0, 0, HttpParseResult.InvalidFormat); AssertGetCommentLength("(x(((((((((x ", 0, 0, HttpParseResult.InvalidFormat); + AssertGetCommentLength("(text\r\n new line)", 0, 0, HttpParseResult.InvalidFormat); // To prevent attacker from sending comments resulting in stack overflow exceptions, we limit the depth // of nested comments. I.e. the following comment is considered invalid since it is considered a @@ -284,15 +284,18 @@ public void GetWhitespaceLength_SetOfValidWhitespaces_ParsedCorrectly() Assert.Equal(1, HttpRuleParser.GetWhitespaceLength("a\t", 1)); Assert.Equal(3, HttpRuleParser.GetWhitespaceLength("a\t ", 1)); Assert.Equal(2, HttpRuleParser.GetWhitespaceLength("\t b", 0)); + } - // Newlines - Assert.Equal(3, HttpRuleParser.GetWhitespaceLength("a\r\n b", 1)); - Assert.Equal(3, HttpRuleParser.GetWhitespaceLength("\r\n ", 0)); - Assert.Equal(3, HttpRuleParser.GetWhitespaceLength("\r\n\t", 0)); - Assert.Equal(13, HttpRuleParser.GetWhitespaceLength(" \r\n\t\t \r\n ", 0)); + [Fact] + public void GetWhitespaceLength_NewLines_NotAllowed() + { + Assert.Equal(0, HttpRuleParser.GetWhitespaceLength("a\r\n b", 1)); + Assert.Equal(0, HttpRuleParser.GetWhitespaceLength("\r\n ", 0)); + Assert.Equal(0, HttpRuleParser.GetWhitespaceLength("\r\n\t", 0)); + Assert.Equal(2, HttpRuleParser.GetWhitespaceLength(" \r\n\t\t \r\n ", 0)); Assert.Equal(1, HttpRuleParser.GetWhitespaceLength(" \r\n", 0)); // first char considered valid whitespace Assert.Equal(1, HttpRuleParser.GetWhitespaceLength(" \r\n\r\n ", 0)); - Assert.Equal(3, HttpRuleParser.GetWhitespaceLength(" \r\n\r\n ", 3)); + Assert.Equal(0, HttpRuleParser.GetWhitespaceLength(" \r\n\r\n ", 3)); } [Fact]