Use Utf8Parser instead of custom code (#1200)
This commit is contained in:
parent
66ab939cff
commit
588d9cdb11
|
|
@ -2,13 +2,13 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers.Text;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
||||
{
|
||||
public static class LengthPrefixedTextMessageParser
|
||||
{
|
||||
private const int Int32OverflowLength = 10;
|
||||
private const char FieldDelimiter = ':';
|
||||
private const char MessageDelimiter = ';';
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
|||
|
||||
var lengthSpan = buffer.Slice(0, index);
|
||||
|
||||
if (!TryParseInt32(lengthSpan, out length, out var bytesConsumed) || bytesConsumed < lengthSpan.Length)
|
||||
if (!Utf8Parser.TryParse(buffer, out length, out var bytesConsumed) || bytesConsumed < lengthSpan.Length)
|
||||
{
|
||||
throw new FormatException($"Invalid length: '{Encoding.UTF8.GetString(lengthSpan.ToArray())}'");
|
||||
}
|
||||
|
|
@ -90,96 +90,5 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryParseInt32(ReadOnlySpan<byte> text, out int value, out int bytesConsumed)
|
||||
{
|
||||
if (text.Length < 1)
|
||||
{
|
||||
bytesConsumed = 0;
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
int indexOfFirstDigit = 0;
|
||||
int sign = 1;
|
||||
if (text[0] == '-')
|
||||
{
|
||||
indexOfFirstDigit = 1;
|
||||
sign = -1;
|
||||
}
|
||||
else if (text[0] == '+')
|
||||
{
|
||||
indexOfFirstDigit = 1;
|
||||
}
|
||||
|
||||
int overflowLength = Int32OverflowLength + indexOfFirstDigit;
|
||||
|
||||
// Parse the first digit separately. If invalid here, we need to return false.
|
||||
int firstDigit = text[indexOfFirstDigit] - 48; // '0'
|
||||
if (firstDigit < 0 || firstDigit > 9)
|
||||
{
|
||||
bytesConsumed = 0;
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
int parsedValue = firstDigit;
|
||||
|
||||
if (text.Length < overflowLength)
|
||||
{
|
||||
// Length is less than Int32OverflowLength; overflow is not possible
|
||||
for (int index = indexOfFirstDigit + 1; index < text.Length; index++)
|
||||
{
|
||||
int nextDigit = text[index] - 48; // '0'
|
||||
if (nextDigit < 0 || nextDigit > 9)
|
||||
{
|
||||
bytesConsumed = index;
|
||||
value = parsedValue * sign;
|
||||
return true;
|
||||
}
|
||||
parsedValue = parsedValue * 10 + nextDigit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Length is greater than Int32OverflowLength; overflow is only possible after Int32OverflowLength
|
||||
// digits. There may be no overflow after Int32OverflowLength if there are leading zeroes.
|
||||
for (int index = indexOfFirstDigit + 1; index < overflowLength - 1; index++)
|
||||
{
|
||||
int nextDigit = text[index] - 48; // '0'
|
||||
if (nextDigit < 0 || nextDigit > 9)
|
||||
{
|
||||
bytesConsumed = index;
|
||||
value = parsedValue * sign;
|
||||
return true;
|
||||
}
|
||||
parsedValue = parsedValue * 10 + nextDigit;
|
||||
}
|
||||
for (int index = overflowLength - 1; index < text.Length; index++)
|
||||
{
|
||||
int nextDigit = text[index] - 48; // '0'
|
||||
if (nextDigit < 0 || nextDigit > 9)
|
||||
{
|
||||
bytesConsumed = index;
|
||||
value = parsedValue * sign;
|
||||
return true;
|
||||
}
|
||||
// If parsedValue > (int.MaxValue / 10), any more appended digits will cause overflow.
|
||||
// if parsedValue == (int.MaxValue / 10), any nextDigit greater than 7 or 8 (depending on sign) implies overflow.
|
||||
bool positive = sign > 0;
|
||||
bool nextDigitTooLarge = nextDigit > 8 || (positive && nextDigit > 7);
|
||||
if (parsedValue > int.MaxValue / 10 || parsedValue == int.MaxValue / 10 && nextDigitTooLarge)
|
||||
{
|
||||
bytesConsumed = 0;
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
parsedValue = parsedValue * 10 + nextDigit;
|
||||
}
|
||||
}
|
||||
|
||||
bytesConsumed = text.Length;
|
||||
value = parsedValue * sign;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue