Only format non-negative int64 #760
This commit is contained in:
parent
b9bba9cbb1
commit
15adff9433
|
|
@ -156,7 +156,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
{ typeof(RangeHeaderValue), new Func<string, RangeHeaderValue>(value => { RangeHeaderValue result; return RangeHeaderValue.TryParse(value, out result) ? result : null; }) },
|
||||
{ typeof(EntityTagHeaderValue), new Func<string, EntityTagHeaderValue>(value => { EntityTagHeaderValue result; return EntityTagHeaderValue.TryParse(value, out result) ? result : null; }) },
|
||||
{ typeof(DateTimeOffset?), new Func<string, DateTimeOffset?>(value => { DateTimeOffset result; return HeaderUtilities.TryParseDate(value, out result) ? result : (DateTimeOffset?)null; }) },
|
||||
{ typeof(long?), new Func<string, long?>(value => { long result; return HeaderUtilities.TryParseInt64(value, out result) ? result : (long?)null; }) },
|
||||
{ typeof(long?), new Func<string, long?>(value => { long result; return HeaderUtilities.TryParseNonNegativeInt64(value, out result) ? result : (long?)null; }) },
|
||||
};
|
||||
|
||||
private static IDictionary<Type, object> KnownListParsers = new Dictionary<Type, object>()
|
||||
|
|
|
|||
|
|
@ -97,11 +97,11 @@ namespace Microsoft.AspNetCore.Http.Headers
|
|||
{
|
||||
get
|
||||
{
|
||||
return Headers.Get<long?>(HeaderNames.ContentLength);
|
||||
return Headers.ContentLength;
|
||||
}
|
||||
set
|
||||
{
|
||||
Headers.Set(HeaderNames.ContentLength, value.HasValue ? HeaderUtilities.FormatInt64(value.Value) : null);
|
||||
Headers.ContentLength = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,11 +50,11 @@ namespace Microsoft.AspNetCore.Http.Headers
|
|||
{
|
||||
get
|
||||
{
|
||||
return Headers.Get<long?>(HeaderNames.ContentLength);
|
||||
return Headers.ContentLength;
|
||||
}
|
||||
set
|
||||
{
|
||||
Headers.Set(HeaderNames.ContentLength, value.HasValue ? HeaderUtilities.FormatInt64(value.Value) : null);
|
||||
Headers.ContentLength = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
var rawValue = this[HeaderNames.ContentLength];
|
||||
if (rawValue.Count == 1 &&
|
||||
!string.IsNullOrWhiteSpace(rawValue[0]) &&
|
||||
HeaderUtilities.TryParseInt64(new StringSegment(rawValue[0]).Trim(), out value))
|
||||
HeaderUtilities.TryParseNonNegativeInt64(new StringSegment(rawValue[0]).Trim(), out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
this[HeaderNames.ContentLength] = HeaderUtilities.FormatInt64(value.Value);
|
||||
this[HeaderNames.ContentLength] = HeaderUtilities.FormatNonNegativeInt64(value.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Owin
|
|||
|
||||
if (rawValue.Length == 1 &&
|
||||
!string.IsNullOrWhiteSpace(rawValue[0]) &&
|
||||
HeaderUtilities.TryParseInt64(new StringSegment(rawValue[0]).Trim(), out value))
|
||||
HeaderUtilities.TryParseNonNegativeInt64(new StringSegment(rawValue[0]).Trim(), out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.Owin
|
|||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
Inner[HeaderNames.ContentLength] = (StringValues)HeaderUtilities.FormatInt64(value.Value);
|
||||
Inner[HeaderNames.ContentLength] = (StringValues)HeaderUtilities.FormatNonNegativeInt64(value.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -610,7 +610,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
int seconds;
|
||||
if (!HeaderUtilities.TryParseInt32(nameValue.Value, out seconds))
|
||||
if (!HeaderUtilities.TryParseNonNegativeInt32(nameValue.Value, out seconds))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
if (sizeParameter != null)
|
||||
{
|
||||
var sizeString = sizeParameter.Value;
|
||||
if (HeaderUtilities.TryParseInt64(sizeString, out value))
|
||||
if (HeaderUtilities.TryParseNonNegativeInt64(sizeString, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -354,13 +354,13 @@ namespace Microsoft.Net.Http.Headers
|
|||
parsedValue = null;
|
||||
|
||||
long from = 0;
|
||||
if ((fromLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(fromStartIndex, fromLength), out from))
|
||||
if ((fromLength > 0) && !HeaderUtilities.TryParseNonNegativeInt64(input.Substring(fromStartIndex, fromLength), out from))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
long to = 0;
|
||||
if ((toLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(toStartIndex, toLength), out to))
|
||||
if ((toLength > 0) && !HeaderUtilities.TryParseNonNegativeInt64(input.Substring(toStartIndex, toLength), out to))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -372,7 +372,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
long length = 0;
|
||||
if ((lengthLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(lengthStartIndex, lengthLength),
|
||||
if ((lengthLength > 0) && !HeaderUtilities.TryParseNonNegativeInt64(input.Substring(lengthStartIndex, lengthLength),
|
||||
out length))
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
{
|
||||
public static class HeaderUtilities
|
||||
{
|
||||
private static readonly int _int64MaxStringLength = 20;
|
||||
private static readonly int _int64MaxStringLength = 19;
|
||||
private const string QualityName = "q";
|
||||
internal const string BytesUnit = "bytes";
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
var tokenLength = HttpRuleParser.GetTokenLength(headerValues[i], current);
|
||||
if (tokenLength == targetValue.Length
|
||||
&& string.Compare(headerValues[i], current, targetValue, 0, tokenLength, StringComparison.OrdinalIgnoreCase) == 0
|
||||
&& TryParseInt64FromHeaderValue(current + tokenLength, headerValues[i], out seconds))
|
||||
&& TryParseNonNegativeInt64FromHeaderValue(current + tokenLength, headerValues[i], out seconds))
|
||||
{
|
||||
// Token matches target value and seconds were parsed
|
||||
value = TimeSpan.FromSeconds(seconds);
|
||||
|
|
@ -342,7 +342,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
return false;
|
||||
}
|
||||
|
||||
private static unsafe bool TryParseInt64FromHeaderValue(int startIndex, string headerValue, out long result)
|
||||
private static unsafe bool TryParseNonNegativeInt64FromHeaderValue(int startIndex, string headerValue, out long result)
|
||||
{
|
||||
// Trim leading whitespace
|
||||
startIndex += HttpRuleParser.GetWhitespaceLength(headerValue, startIndex);
|
||||
|
|
@ -359,7 +359,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
startIndex += HttpRuleParser.GetWhitespaceLength(headerValue, startIndex);
|
||||
|
||||
// Try parse the number
|
||||
if (TryParseInt64(new StringSegment(headerValue, startIndex, HttpRuleParser.GetNumberLength(headerValue, startIndex, false)), out result))
|
||||
if (TryParseNonNegativeInt64(new StringSegment(headerValue, startIndex, HttpRuleParser.GetNumberLength(headerValue, startIndex, false)), out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -368,9 +368,9 @@ namespace Microsoft.Net.Http.Headers
|
|||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryParseInt32(string value, out int result)
|
||||
internal static bool TryParseNonNegativeInt32(string value, out int result)
|
||||
{
|
||||
return TryParseInt32(new StringSegment(value), out result);
|
||||
return TryParseNonNegativeInt32(new StringSegment(value), out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -388,12 +388,12 @@ namespace Microsoft.Net.Http.Headers
|
|||
/// result will be overwritten.
|
||||
/// </param>
|
||||
/// <returns><code>true</code> if parsing succeeded; otherwise, <code>false</code>.</returns>
|
||||
public static bool TryParseInt64(string value, out long result)
|
||||
public static bool TryParseNonNegativeInt64(string value, out long result)
|
||||
{
|
||||
return TryParseInt64(new StringSegment(value), out result);
|
||||
return TryParseNonNegativeInt64(new StringSegment(value), out result);
|
||||
}
|
||||
|
||||
internal static unsafe bool TryParseInt32(StringSegment value, out int result)
|
||||
internal static unsafe bool TryParseNonNegativeInt32(StringSegment value, out int result)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value.Buffer) || value.Length == 0)
|
||||
{
|
||||
|
|
@ -444,7 +444,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
/// originally supplied in result will be overwritten.
|
||||
/// </param>
|
||||
/// <returns><code>true</code> if parsing succeeded; otherwise, <code>false</code>.</returns>
|
||||
public static unsafe bool TryParseInt64(StringSegment value, out long result)
|
||||
public static unsafe bool TryParseNonNegativeInt64(StringSegment value, out long result)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value.Buffer) || value.Length == 0)
|
||||
{
|
||||
|
|
@ -481,31 +481,22 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the signed 64-bit numeric value to its equivalent string representation.
|
||||
/// Converts the non-negative 64-bit numeric value to its equivalent string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The number to convert.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The string representation of the value of this instance, consisting of a minus sign if the value is
|
||||
/// negative, and a sequence of digits ranging from 0 to 9 with no leading zeroes.
|
||||
/// The string representation of the value of this instance, consisting of a sequence of digits ranging from 0 to 9 with no leading zeroes.
|
||||
/// </returns>
|
||||
public unsafe static string FormatInt64(long value)
|
||||
public unsafe static string FormatNonNegativeInt64(long value)
|
||||
{
|
||||
var position = _int64MaxStringLength;
|
||||
var negative = false;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
// Not possible to compute absolute value of MinValue, return the exact string instead.
|
||||
if (value == long.MinValue)
|
||||
{
|
||||
return "-9223372036854775808";
|
||||
}
|
||||
negative = true;
|
||||
value = -value;
|
||||
throw new ArgumentOutOfRangeException(nameof(value), value, "The value to be formatted must be non-negative.");
|
||||
}
|
||||
|
||||
var position = _int64MaxStringLength;
|
||||
char* charBuffer = stackalloc char[_int64MaxStringLength];
|
||||
|
||||
do
|
||||
|
|
@ -517,11 +508,6 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
while (value != 0);
|
||||
|
||||
if (negative)
|
||||
{
|
||||
charBuffer[--position] = '-';
|
||||
}
|
||||
|
||||
return new string(charBuffer, position, _int64MaxStringLength - position);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -202,14 +202,14 @@ namespace Microsoft.Net.Http.Headers
|
|||
|
||||
// Try convert first value to int64
|
||||
long from = 0;
|
||||
if ((fromLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(fromStartIndex, fromLength), out from))
|
||||
if ((fromLength > 0) && !HeaderUtilities.TryParseNonNegativeInt64(input.Substring(fromStartIndex, fromLength), out from))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try convert second value to int64
|
||||
long to = 0;
|
||||
if ((toLength > 0) && !HeaderUtilities.TryParseInt64(input.Substring(toStartIndex, toLength), out to))
|
||||
if ((toLength > 0) && !HeaderUtilities.TryParseNonNegativeInt64(input.Substring(toStartIndex, toLength), out to))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
|
||||
if (MaxAge.HasValue)
|
||||
{
|
||||
maxAge = HeaderUtilities.FormatInt64((long)MaxAge.Value.TotalSeconds);
|
||||
maxAge = HeaderUtilities.FormatNonNegativeInt64((long)MaxAge.Value.TotalSeconds);
|
||||
length += SeparatorToken.Length + MaxAgeToken.Length + EqualsToken.Length + maxAge.Length;
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
|
||||
if (MaxAge.HasValue)
|
||||
{
|
||||
AppendSegment(builder, MaxAgeToken, HeaderUtilities.FormatInt64((long)MaxAge.Value.TotalSeconds));
|
||||
AppendSegment(builder, MaxAgeToken, HeaderUtilities.FormatNonNegativeInt64((long)MaxAge.Value.TotalSeconds));
|
||||
}
|
||||
|
||||
if (Domain != null)
|
||||
|
|
@ -365,7 +365,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
var numberString = input.Substring(offset, itemLength);
|
||||
long maxAge;
|
||||
if (!HeaderUtilities.TryParseInt64(numberString, out maxAge))
|
||||
if (!HeaderUtilities.TryParseNonNegativeInt64(numberString, out maxAge))
|
||||
{
|
||||
// Invalid expiration date, abort
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -87,15 +87,20 @@ namespace Microsoft.Net.Http.Headers
|
|||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(-1)]
|
||||
[InlineData(1234567890)]
|
||||
[InlineData(-1234567890)]
|
||||
[InlineData(long.MaxValue)]
|
||||
[InlineData(long.MinValue)]
|
||||
[InlineData(long.MinValue + 1)]
|
||||
public void FormatInt64_MatchesToString(long value)
|
||||
public void FormatNonNegativeInt64_MatchesToString(long value)
|
||||
{
|
||||
Assert.Equal(value.ToString(CultureInfo.InvariantCulture), HeaderUtilities.FormatInt64(value));
|
||||
Assert.Equal(value.ToString(CultureInfo.InvariantCulture), HeaderUtilities.FormatNonNegativeInt64(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(-1)]
|
||||
[InlineData(-1234567890)]
|
||||
[InlineData(long.MinValue)]
|
||||
public void FormatNonNegativeInt64_Throws_ForNegativeValues(long value)
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => HeaderUtilities.FormatNonNegativeInt64(value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -150,20 +155,20 @@ namespace Microsoft.Net.Http.Headers
|
|||
[InlineData("a")]
|
||||
[InlineData("1.1")]
|
||||
[InlineData("9223372036854775808")] // long.MaxValue + 1
|
||||
public void TryParseInt64_Fails(string valueString)
|
||||
public void TryParseNonNegativeInt64_Fails(string valueString)
|
||||
{
|
||||
long value = 1;
|
||||
Assert.False(HeaderUtilities.TryParseInt64(valueString, out value));
|
||||
Assert.False(HeaderUtilities.TryParseNonNegativeInt64(valueString, out value));
|
||||
Assert.Equal(0, value);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("0", 0)]
|
||||
[InlineData("9223372036854775807", 9223372036854775807)] // long.MaxValue
|
||||
public void TryParseInt64_Succeeds(string valueString, long expected)
|
||||
public void TryParseNonNegativeInt64_Succeeds(string valueString, long expected)
|
||||
{
|
||||
long value = 1;
|
||||
Assert.True(HeaderUtilities.TryParseInt64(valueString, out value));
|
||||
Assert.True(HeaderUtilities.TryParseNonNegativeInt64(valueString, out value));
|
||||
Assert.Equal(expected, value);
|
||||
}
|
||||
|
||||
|
|
@ -175,20 +180,20 @@ namespace Microsoft.Net.Http.Headers
|
|||
[InlineData("1.1")]
|
||||
[InlineData("1,000")]
|
||||
[InlineData("2147483648")] // int.MaxValue + 1
|
||||
public void TryParseInt32_Fails(string valueString)
|
||||
public void TryParseNonNegativeInt32_Fails(string valueString)
|
||||
{
|
||||
int value = 1;
|
||||
Assert.False(HeaderUtilities.TryParseInt32(valueString, out value));
|
||||
Assert.False(HeaderUtilities.TryParseNonNegativeInt32(valueString, out value));
|
||||
Assert.Equal(0, value);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("0", 0)]
|
||||
[InlineData("2147483647", 2147483647)] // int.MaxValue
|
||||
public void TryParseInt32_Succeeds(string valueString, long expected)
|
||||
public void TryParseNonNegativeInt32_Succeeds(string valueString, long expected)
|
||||
{
|
||||
int value = 1;
|
||||
Assert.True(HeaderUtilities.TryParseInt32(valueString, out value));
|
||||
Assert.True(HeaderUtilities.TryParseNonNegativeInt32(valueString, out value));
|
||||
Assert.Equal(expected, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue