Add check for index advance during parsing
This commit is contained in:
parent
779115b1ad
commit
3289afe007
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
@ -200,6 +201,33 @@ namespace Microsoft.Net.Http.Headers
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int AdvanceCacheDirectiveIndex(int current, string headerValue)
|
||||||
|
{
|
||||||
|
// Skip until the next potential name
|
||||||
|
current += HttpRuleParser.GetWhitespaceLength(headerValue, current);
|
||||||
|
|
||||||
|
// Skip the value if present
|
||||||
|
if (current < headerValue.Length && headerValue[current] == '=')
|
||||||
|
{
|
||||||
|
current++; // skip '='
|
||||||
|
current += NameValueHeaderValue.GetValueLength(headerValue, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next delimiter
|
||||||
|
current = headerValue.IndexOf(',', current);
|
||||||
|
|
||||||
|
if (current == -1)
|
||||||
|
{
|
||||||
|
// If no delimiter found, skip to the end
|
||||||
|
return headerValue.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
current++; // skip ','
|
||||||
|
current += HttpRuleParser.GetWhitespaceLength(headerValue, current);
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to find a target header value among the set of given header values and parse it as a
|
/// Try to find a target header value among the set of given header values and parse it as a
|
||||||
/// <see cref="TimeSpan"/>.
|
/// <see cref="TimeSpan"/>.
|
||||||
|
|
@ -237,6 +265,7 @@ namespace Microsoft.Net.Http.Headers
|
||||||
while (current < headerValues[i].Length)
|
while (current < headerValues[i].Length)
|
||||||
{
|
{
|
||||||
long seconds;
|
long seconds;
|
||||||
|
var initial = current;
|
||||||
var tokenLength = HttpRuleParser.GetTokenLength(headerValues[i], current);
|
var tokenLength = HttpRuleParser.GetTokenLength(headerValues[i], current);
|
||||||
if (tokenLength == targetValue.Length
|
if (tokenLength == targetValue.Length
|
||||||
&& string.Compare(headerValues[i], current, targetValue, 0, tokenLength, StringComparison.OrdinalIgnoreCase) == 0
|
&& string.Compare(headerValues[i], current, targetValue, 0, tokenLength, StringComparison.OrdinalIgnoreCase) == 0
|
||||||
|
|
@ -246,26 +275,15 @@ namespace Microsoft.Net.Http.Headers
|
||||||
value = TimeSpan.FromSeconds(seconds);
|
value = TimeSpan.FromSeconds(seconds);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
current = AdvanceCacheDirectiveIndex(current + tokenLength, headerValues[i]);
|
||||||
|
|
||||||
|
// Ensure index was advanced
|
||||||
|
if (current <= initial)
|
||||||
{
|
{
|
||||||
// Skip until the next potential name
|
Debug.Assert(false, $"Index '{nameof(current)}' not advanced, this is a bug.");
|
||||||
current += tokenLength;
|
value = null;
|
||||||
current += HttpRuleParser.GetWhitespaceLength(headerValues[i], current);
|
return false;
|
||||||
|
|
||||||
// Skip the value if present
|
|
||||||
if (current < headerValues[i].Length && headerValues[i][current] == '=')
|
|
||||||
{
|
|
||||||
current++; // skip '='
|
|
||||||
current += NameValueHeaderValue.GetValueLength(headerValues[i], current);
|
|
||||||
current += HttpRuleParser.GetWhitespaceLength(headerValues[i], current);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the delimiter
|
|
||||||
if (current < headerValues[i].Length && headerValues[i][current] == ',')
|
|
||||||
{
|
|
||||||
current++; // skip ','
|
|
||||||
current += HttpRuleParser.GetWhitespaceLength(headerValues[i], current);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +311,6 @@ namespace Microsoft.Net.Http.Headers
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (var i = 0; i < cacheControlDirectives.Count; i++)
|
for (var i = 0; i < cacheControlDirectives.Count; i++)
|
||||||
{
|
{
|
||||||
// Trim leading white space
|
// Trim leading white space
|
||||||
|
|
@ -301,6 +318,8 @@ namespace Microsoft.Net.Http.Headers
|
||||||
|
|
||||||
while (current < cacheControlDirectives[i].Length)
|
while (current < cacheControlDirectives[i].Length)
|
||||||
{
|
{
|
||||||
|
var initial = current;
|
||||||
|
|
||||||
var tokenLength = HttpRuleParser.GetTokenLength(cacheControlDirectives[i], current);
|
var tokenLength = HttpRuleParser.GetTokenLength(cacheControlDirectives[i], current);
|
||||||
if (tokenLength == targetDirectives.Length
|
if (tokenLength == targetDirectives.Length
|
||||||
&& string.Compare(cacheControlDirectives[i], current, targetDirectives, 0, tokenLength, StringComparison.OrdinalIgnoreCase) == 0)
|
&& string.Compare(cacheControlDirectives[i], current, targetDirectives, 0, tokenLength, StringComparison.OrdinalIgnoreCase) == 0)
|
||||||
|
|
@ -308,26 +327,14 @@ namespace Microsoft.Net.Http.Headers
|
||||||
// Token matches target value
|
// Token matches target value
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
current = AdvanceCacheDirectiveIndex(current + tokenLength, cacheControlDirectives[i]);
|
||||||
|
|
||||||
|
// Ensure index was advanced
|
||||||
|
if (current <= initial)
|
||||||
{
|
{
|
||||||
// Skip until the next potential name
|
Debug.Assert(false, $"Index '{nameof(current)}' not advanced, this is a bug.");
|
||||||
current += tokenLength;
|
return false;
|
||||||
current += HttpRuleParser.GetWhitespaceLength(cacheControlDirectives[i], current);
|
|
||||||
|
|
||||||
// Skip the value if present
|
|
||||||
if (current < cacheControlDirectives[i].Length && cacheControlDirectives[i][current] == '=')
|
|
||||||
{
|
|
||||||
current++; // skip '='
|
|
||||||
current += NameValueHeaderValue.GetValueLength(cacheControlDirectives[i], current);
|
|
||||||
current += HttpRuleParser.GetWhitespaceLength(cacheControlDirectives[i], current);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the delimiter
|
|
||||||
if (current < cacheControlDirectives[i].Length && cacheControlDirectives[i][current] == ',')
|
|
||||||
{
|
|
||||||
current++; // skip ','
|
|
||||||
current += HttpRuleParser.GetWhitespaceLength(cacheControlDirectives[i], current);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ namespace Microsoft.Net.Http.Headers
|
||||||
[InlineData("directive1", "directive")]
|
[InlineData("directive1", "directive")]
|
||||||
[InlineData("h=directive", "directive")]
|
[InlineData("h=directive", "directive")]
|
||||||
[InlineData("directive1, directive2=80", "directive")]
|
[InlineData("directive1, directive2=80", "directive")]
|
||||||
|
[InlineData("directive1=;, directive2=10", "directive1")]
|
||||||
public void TryParseSeconds_Fails(string headerValues, string targetValue)
|
public void TryParseSeconds_Fails(string headerValues, string targetValue)
|
||||||
{
|
{
|
||||||
TimeSpan? value;
|
TimeSpan? value;
|
||||||
|
|
@ -124,6 +125,7 @@ namespace Microsoft.Net.Http.Headers
|
||||||
[InlineData("directive1", "directive", false)]
|
[InlineData("directive1", "directive", false)]
|
||||||
[InlineData("h=directive", "directive", false)]
|
[InlineData("h=directive", "directive", false)]
|
||||||
[InlineData("directive1, directive2=80", "directive", false)]
|
[InlineData("directive1, directive2=80", "directive", false)]
|
||||||
|
[InlineData("directive1;, directive2=80", "directive", false)]
|
||||||
public void ContainsCacheDirective_MatchesExactValue(string headerValues, string targetValue, bool contains)
|
public void ContainsCacheDirective_MatchesExactValue(string headerValues, string targetValue, bool contains)
|
||||||
{
|
{
|
||||||
Assert.Equal(contains, HeaderUtilities.ContainsCacheDirective(new StringValues(headerValues), targetValue));
|
Assert.Equal(contains, HeaderUtilities.ContainsCacheDirective(new StringValues(headerValues), targetValue));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue