Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 524cdb7

Browse files
committed
Add tests for parsing Int32
1 parent f548465 commit 524cdb7

File tree

2 files changed

+111
-6
lines changed

2 files changed

+111
-6
lines changed

src/ServiceStack.Text/Support/StringSegmentExtensions.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,29 +241,38 @@ private static ulong ParseUnsignedInteger(StringSegment value, ulong maxValue)
241241
}
242242
}
243243

244+
if (state != ParseState.Number && state != ParseState.TrailingWhite)
245+
throw new FormatException(BadFormat);
246+
244247
return result;
245248
}
246249

247250
private static long ParseSignedInteger(StringSegment value, long maxValue, long minValue)
248251
{
252+
if (value.Buffer == null)
253+
throw new ArgumentNullException();
254+
249255
if (value.Length == 0)
250256
throw new FormatException(BadFormat);
251257

252258
long result = 0;
253-
int i = 0;
259+
int i = value.Offset;
260+
int end = value.Offset + value.Length;
254261
var state = ParseState.LeadingWhite;
255262
bool negative = false;
256263

257-
while (i < value.Length)
264+
//skip leading whitespaces
265+
while (i < end && JsonUtils.IsWhiteSpace(value.Buffer[i])) i++;
266+
if (i == end)
267+
throw new FormatException(BadFormat);
268+
269+
while (i < end)
258270
{
259-
var c = value.GetChar(i++);
271+
var c = value.Buffer[i++];
260272

261273
switch (state)
262274
{
263275
case ParseState.LeadingWhite:
264-
if (JsonUtils.IsWhiteSpace(c))
265-
break;
266-
267276
if (c == '-')
268277
{
269278
negative = true;
@@ -323,6 +332,9 @@ private static long ParseSignedInteger(StringSegment value, long maxValue, long
323332
}
324333
}
325334

335+
if (state != ParseState.Number && state != ParseState.TrailingWhite)
336+
throw new FormatException(BadFormat);
337+
326338
if (negative)
327339
return result;
328340

tests/ServiceStack.Text.Tests/Support/StringSegmentParse.cs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using NUnit.Framework;
22
using ServiceStack.Text.Support;
33
using System;
4+
using System.Collections.Generic;
45
using System.Globalization;
56
#if NETCORE
67
using Microsoft.Extensions.Primitives;
@@ -36,6 +37,98 @@ public void Can_parse_int32()
3637
Assert.Throws<FormatException>(() => new StringSegment(" 1234 123").ParseInt32());
3738
}
3839

40+
[Test]
41+
public void Can_parse_invalid_int32()
42+
{
43+
foreach (var data in Parse_Invalid_TestData())
44+
{
45+
Assert.Throws((Type)data[3], () => new StringSegment((string) data[0]).ParseInt32());
46+
}
47+
}
48+
49+
50+
//ivalid tests data from
51+
//https://github.com/dotnet/corefx/blob/df8d8ac7c49e6c4acdce2ea684d8815be5da6a25/src/System.Runtime/tests/System/Int32Tests.cs#L150
52+
public static IEnumerable<object[]> Parse_Invalid_TestData()
53+
{
54+
// String is null, empty or entirely whitespace
55+
yield return new object[] { null, NumberStyles.Integer, null, typeof(ArgumentNullException) };
56+
yield return new object[] { null, NumberStyles.Any, null, typeof(ArgumentNullException) };
57+
yield return new object[] { "", NumberStyles.Integer, null, typeof(FormatException) };
58+
yield return new object[] { "", NumberStyles.Any, null, typeof(FormatException) };
59+
yield return new object[] { " \t \n \r ", NumberStyles.Integer, null, typeof(FormatException) };
60+
yield return new object[] { " \t \n \r ", NumberStyles.Any, null, typeof(FormatException) };
61+
62+
// String is garbage
63+
yield return new object[] { "Garbage", NumberStyles.Integer, null, typeof(FormatException) };
64+
yield return new object[] { "Garbage", NumberStyles.Any, null, typeof(FormatException) };
65+
66+
// String has leading zeros
67+
yield return new object[] { "\0\0123", NumberStyles.Integer, null, typeof(FormatException) };
68+
yield return new object[] { "\0\0123", NumberStyles.Any, null, typeof(FormatException) };
69+
70+
// String has internal zeros
71+
yield return new object[] { "1\023", NumberStyles.Integer, null, typeof(FormatException) };
72+
yield return new object[] { "1\023", NumberStyles.Any, null, typeof(FormatException) };
73+
74+
// Integer doesn't allow hex, exponents, paretheses, currency, thousands, decimal
75+
yield return new object[] { "abc", NumberStyles.Integer, null, typeof(FormatException) };
76+
yield return new object[] { "1E23", NumberStyles.Integer, null, typeof(FormatException) };
77+
yield return new object[] { "(123)", NumberStyles.Integer, null, typeof(FormatException) };
78+
yield return new object[] { 1000.ToString("C0"), NumberStyles.Integer, null, typeof(FormatException) };
79+
yield return new object[] { 1000.ToString("N0"), NumberStyles.Integer, null, typeof(FormatException) };
80+
yield return new object[] { 678.90.ToString("F2"), NumberStyles.Integer, null, typeof(FormatException) };
81+
82+
// HexNumber
83+
yield return new object[] { "0xabc", NumberStyles.HexNumber, null, typeof(FormatException) };
84+
yield return new object[] { "&habc", NumberStyles.HexNumber, null, typeof(FormatException) };
85+
yield return new object[] { "G1", NumberStyles.HexNumber, null, typeof(FormatException) };
86+
yield return new object[] { "g1", NumberStyles.HexNumber, null, typeof(FormatException) };
87+
yield return new object[] { "+abc", NumberStyles.HexNumber, null, typeof(FormatException) };
88+
yield return new object[] { "-abc", NumberStyles.HexNumber, null, typeof(FormatException) };
89+
90+
// AllowLeadingSign
91+
yield return new object[] { "+", NumberStyles.AllowLeadingSign, null, typeof(FormatException) };
92+
yield return new object[] { "-", NumberStyles.AllowLeadingSign, null, typeof(FormatException) };
93+
yield return new object[] { "+-123", NumberStyles.AllowLeadingSign, null, typeof(FormatException) };
94+
yield return new object[] { "-+123", NumberStyles.AllowLeadingSign, null, typeof(FormatException) };
95+
yield return new object[] { "- 123", NumberStyles.AllowLeadingSign, null, typeof(FormatException) };
96+
yield return new object[] { "+ 123", NumberStyles.AllowLeadingSign, null, typeof(FormatException) };
97+
98+
// AllowTrailingSign
99+
yield return new object[] { "123-+", NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
100+
yield return new object[] { "123+-", NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
101+
yield return new object[] { "123 -", NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
102+
yield return new object[] { "123 +", NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
103+
104+
// Parentheses has priority over CurrencySymbol and PositiveSign
105+
NumberFormatInfo currencyNegativeParenthesesFormat = new NumberFormatInfo()
106+
{
107+
CurrencySymbol = "(",
108+
PositiveSign = "))"
109+
};
110+
yield return new object[] { "(100))", NumberStyles.AllowParentheses | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowTrailingSign, currencyNegativeParenthesesFormat, typeof(FormatException) };
111+
112+
// AllowTrailingSign and AllowLeadingSign
113+
yield return new object[] { "+123+", NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
114+
yield return new object[] { "+123-", NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
115+
yield return new object[] { "-123+", NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
116+
yield return new object[] { "-123-", NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign, null, typeof(FormatException) };
117+
118+
// AllowLeadingSign and AllowParentheses
119+
yield return new object[] { "-(1000)", NumberStyles.AllowLeadingSign | NumberStyles.AllowParentheses, null, typeof(FormatException) };
120+
yield return new object[] { "(-1000)", NumberStyles.AllowLeadingSign | NumberStyles.AllowParentheses, null, typeof(FormatException) };
121+
122+
// Not in range of Int32
123+
yield return new object[] { "2147483648", NumberStyles.Any, null, typeof(OverflowException) };
124+
yield return new object[] { "2147483648", NumberStyles.Integer, null, typeof(OverflowException) };
125+
yield return new object[] { "-2147483649", NumberStyles.Any, null, typeof(OverflowException) };
126+
yield return new object[] { "-2147483649", NumberStyles.Integer, null, typeof(OverflowException) };
127+
128+
yield return new object[] { "9223372036854775808", NumberStyles.Integer, null, typeof(OverflowException) };
129+
yield return new object[] { "-9223372036854775809", NumberStyles.Integer, null, typeof(OverflowException) };
130+
}
131+
39132
[Test]
40133
public void Can_parse_decimal()
41134
{

0 commit comments

Comments
 (0)