Skip to content

Commit

Permalink
Handle number overflow during parsing of min/max values
Browse files Browse the repository at this point in the history
  • Loading branch information
Robulane committed Nov 22, 2023
1 parent 47ed933 commit 4bc07e3
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 9 deletions.
35 changes: 35 additions & 0 deletions src/Microsoft.OpenApi.Readers/ParseNodes/ParserHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.Globalization;

namespace Microsoft.OpenApi.Readers.ParseNodes
{
/// <summary>
/// Useful tools to parse data
/// </summary>
internal class ParserHelper
{
/// <summary>
/// Parses decimal in invariant culture.
/// If the decimal is too big or small, it returns the default value
///
/// 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.
/// 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.
/// We can revisit this if somebody really needs to have double or long here.
/// </summary>
/// <returns></returns>
public static decimal ParseDecimalWithFallbackOnOverflow(string value, decimal defaultValue)
{
try
{
return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture);
}
catch (OverflowException)
{
return defaultValue;
}
}
}
}
6 changes: 3 additions & 3 deletions src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
Expand Down Expand Up @@ -44,15 +44,15 @@ internal static partial class OpenApiV2Deserializer
},
{
"maximum",
(o, n) => GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
(o, n) => GetOrCreateSchema(o).Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
},
{
"exclusiveMaximum",
(o, n) => GetOrCreateSchema(o).ExclusiveMaximum = bool.Parse(n.GetScalarValue())
},
{
"minimum",
(o, n) => GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
(o, n) => GetOrCreateSchema(o).Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
},
{
"exclusiveMinimum",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ internal static partial class OpenApiV2Deserializer
},
{
"minimum",
(o, n) => GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
(o, n) => GetOrCreateSchema(o).Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
},
{
"maximum",
(o, n) => GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
(o, n) => GetOrCreateSchema(o).Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
},
{
"maxLength",
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ internal static partial class OpenApiV2Deserializer
},
{
"maximum",
(o, n) => o.Maximum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
(o, n) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
},
{
"exclusiveMaximum",
(o, n) => o.ExclusiveMaximum = bool.Parse(n.GetScalarValue())
},
{
"minimum",
(o, n) => o.Minimum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
(o, n) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
},
{
"exclusiveMinimum",
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ internal static partial class OpenApiV3Deserializer
},
{
"maximum",
(o, n) => o.Maximum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
(o, n) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
},
{
"exclusiveMaximum",
(o, n) => o.ExclusiveMaximum = bool.Parse(n.GetScalarValue())
},
{
"minimum",
(o, n) => o.Minimum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
(o, n) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
},
{
"exclusiveMinimum",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using Microsoft.OpenApi.Readers.ParseNodes;
using Xunit;

namespace Microsoft.OpenApi.Readers.Tests.ParseNodes
{
[Collection("DefaultSettings")]
public class ParserHelperTests
{
[Fact]
public void ParseDecimalWithFallbackOnOverflow_ReturnsParsedValue()
{
Assert.Equal(23434, ParserHelper.ParseDecimalWithFallbackOnOverflow("23434", 10));
}

[Fact]
public void ParseDecimalWithFallbackOnOverflow_Overflows_ReturnsFallback()
{
Assert.Equal(10, ParserHelper.ParseDecimalWithFallbackOnOverflow(double.MaxValue.ToString(), 10));
}
}
}

0 comments on commit 4bc07e3

Please sign in to comment.