Skip to content

Commit 4bc07e3

Browse files
committed
Handle number overflow during parsing of min/max values
1 parent 47ed933 commit 4bc07e3

File tree

6 files changed

+68
-9
lines changed

6 files changed

+68
-9
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using System;
5+
using System.Globalization;
6+
7+
namespace Microsoft.OpenApi.Readers.ParseNodes
8+
{
9+
/// <summary>
10+
/// Useful tools to parse data
11+
/// </summary>
12+
internal class ParserHelper
13+
{
14+
/// <summary>
15+
/// Parses decimal in invariant culture.
16+
/// If the decimal is too big or small, it returns the default value
17+
///
18+
/// Note: sometimes developers put Double.MaxValue or Long.MaxValue as min/max values for numbers in json schema even if their numbers are not expected to be that big/small.
19+
/// As we have already released the library with Decimal type for Max/Min, let's not introduce the breaking change and just fallback to Decimal.Max / Min. This should satisfy almost every scenario.
20+
/// We can revisit this if somebody really needs to have double or long here.
21+
/// </summary>
22+
/// <returns></returns>
23+
public static decimal ParseDecimalWithFallbackOnOverflow(string value, decimal defaultValue)
24+
{
25+
try
26+
{
27+
return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture);
28+
}
29+
catch (OverflowException)
30+
{
31+
return defaultValue;
32+
}
33+
}
34+
}
35+
}

src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

44
using System;
@@ -44,15 +44,15 @@ internal static partial class OpenApiV2Deserializer
4444
},
4545
{
4646
"maximum",
47-
(o, n) => GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
47+
(o, n) => GetOrCreateSchema(o).Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
4848
},
4949
{
5050
"exclusiveMaximum",
5151
(o, n) => GetOrCreateSchema(o).ExclusiveMaximum = bool.Parse(n.GetScalarValue())
5252
},
5353
{
5454
"minimum",
55-
(o, n) => GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
55+
(o, n) => GetOrCreateSchema(o).Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
5656
},
5757
{
5858
"exclusiveMinimum",

src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ internal static partial class OpenApiV2Deserializer
6161
},
6262
{
6363
"minimum",
64-
(o, n) => GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
64+
(o, n) => GetOrCreateSchema(o).Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
6565
},
6666
{
6767
"maximum",
68-
(o, n) => GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
68+
(o, n) => GetOrCreateSchema(o).Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
6969
},
7070
{
7171
"maxLength",

src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ internal static partial class OpenApiV2Deserializer
2727
},
2828
{
2929
"maximum",
30-
(o, n) => o.Maximum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
30+
(o, n) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
3131
},
3232
{
3333
"exclusiveMaximum",
3434
(o, n) => o.ExclusiveMaximum = bool.Parse(n.GetScalarValue())
3535
},
3636
{
3737
"minimum",
38-
(o, n) => o.Minimum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
38+
(o, n) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
3939
},
4040
{
4141
"exclusiveMinimum",

src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ internal static partial class OpenApiV3Deserializer
2727
},
2828
{
2929
"maximum",
30-
(o, n) => o.Maximum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
30+
(o, n) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
3131
},
3232
{
3333
"exclusiveMaximum",
3434
(o, n) => o.ExclusiveMaximum = bool.Parse(n.GetScalarValue())
3535
},
3636
{
3737
"minimum",
38-
(o, n) => o.Minimum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
38+
(o, n) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
3939
},
4040
{
4141
"exclusiveMinimum",
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using Microsoft.OpenApi.Readers.ParseNodes;
5+
using Xunit;
6+
7+
namespace Microsoft.OpenApi.Readers.Tests.ParseNodes
8+
{
9+
[Collection("DefaultSettings")]
10+
public class ParserHelperTests
11+
{
12+
[Fact]
13+
public void ParseDecimalWithFallbackOnOverflow_ReturnsParsedValue()
14+
{
15+
Assert.Equal(23434, ParserHelper.ParseDecimalWithFallbackOnOverflow("23434", 10));
16+
}
17+
18+
[Fact]
19+
public void ParseDecimalWithFallbackOnOverflow_Overflows_ReturnsFallback()
20+
{
21+
Assert.Equal(10, ParserHelper.ParseDecimalWithFallbackOnOverflow(double.MaxValue.ToString(), 10));
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)