From 73203653ba77185cd907dd1ac6e7c4fc7a53c6b3 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 17 Feb 2018 18:04:00 +1300 Subject: [PATCH] -Fixed unhelpful error when failing conversion in JsonReader.ReadAsInt32 --- .../JsonTextReaderTests/ReadAsyncTests.cs | 10 ++ .../JsonTextReaderTests/ReadTests.cs | 10 ++ .../Serialization/JsonSerializerTest.cs | 15 +++ Src/Newtonsoft.Json/JsonReader.cs | 100 ++++++++++-------- 4 files changed, 93 insertions(+), 42 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadAsyncTests.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadAsyncTests.cs index d5844266..97816c23 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadAsyncTests.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadAsyncTests.cs @@ -56,6 +56,16 @@ namespace Newtonsoft.Json.Tests.JsonTextReaderTests #endif public class ReadAsyncTests : TestFixtureBase { + [Test] + public async Task ReadAsInt32Async_IntegerTooLarge_ThrowsJsonReaderException() + { + JValue token = new JValue(long.MaxValue); + + await ExceptionAssert.ThrowsAsync( + () => token.CreateReader().ReadAsInt32Async() + ); + } + [Test] public async Task ReadMissingInt64() { diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadTests.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadTests.cs index b389fa20..0de4ac31 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadTests.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/ReadTests.cs @@ -61,6 +61,16 @@ namespace Newtonsoft.Json.Tests.JsonTextReaderTests #endif public class ReadTests : TestFixtureBase { + [Test] + public void ReadAsInt32_IntegerTooLarge_ThrowsJsonReaderException() + { + JValue token = new JValue(long.MaxValue); + + ExceptionAssert.Throws( + () => token.CreateReader().ReadAsInt32() + ); + } + [Test] public void ReadMissingInt64() { diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 7ae239a9..4e3fa5dd 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -971,6 +971,11 @@ namespace Newtonsoft.Json.Tests.Serialization { JsonSerializer serializer = new JsonSerializer(); +#pragma warning disable CS0618 // Type or member is obsolete + Assert.IsNotNull(serializer.Binder); +#pragma warning restore CS0618 // Type or member is obsolete + Assert.IsNotNull(serializer.SerializationBinder); + DefaultSerializationBinder customBinder = new DefaultSerializationBinder(); #pragma warning disable CS0618 // Type or member is obsolete serializer.Binder = customBinder; @@ -1090,6 +1095,11 @@ namespace Newtonsoft.Json.Tests.Serialization { JsonSerializerSettings settings = new JsonSerializerSettings(); +#pragma warning disable CS0618 // Type or member is obsolete + Assert.IsNull(settings.Binder); +#pragma warning restore CS0618 // Type or member is obsolete + Assert.IsNull(settings.SerializationBinder); + DefaultSerializationBinder customBinder = new DefaultSerializationBinder(); #pragma warning disable CS0618 // Type or member is obsolete settings.Binder = customBinder; @@ -1205,6 +1215,11 @@ namespace Newtonsoft.Json.Tests.Serialization { JsonSerializerProxy serializerProxy = new JsonSerializerProxy(new JsonSerializerInternalReader(new JsonSerializer())); +#pragma warning disable CS0618 // Type or member is obsolete + Assert.IsNotNull(serializerProxy.Binder); +#pragma warning restore CS0618 // Type or member is obsolete + Assert.IsNotNull(serializerProxy.SerializationBinder); + DefaultSerializationBinder customBinder = new DefaultSerializationBinder(); #pragma warning disable CS0618 // Type or member is obsolete serializerProxy.Binder = customBinder; diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs index 17222f99..2e595138 100644 --- a/Src/Newtonsoft.Json/JsonReader.cs +++ b/Src/Newtonsoft.Json/JsonReader.cs @@ -408,12 +408,24 @@ namespace Newtonsoft.Json return null; case JsonToken.Integer: case JsonToken.Float: - if (!(Value is int)) + object v = Value; + if (v is int i) { - SetToken(JsonToken.Integer, Convert.ToInt32(Value, CultureInfo.InvariantCulture), false); + return i; } - return (int)Value; + try + { + i = Convert.ToInt32(v, CultureInfo.InvariantCulture); + } + catch (Exception ex) + { + // handle error for large integer overflow exceptions + throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, v), ex); + } + + SetToken(JsonToken.Integer, i, false); + return i; case JsonToken.String: string s = (string)Value; return ReadInt32String(s); @@ -462,17 +474,18 @@ namespace Newtonsoft.Json if (JsonTokenUtils.IsPrimitiveToken(t)) { - if (Value != null) + object v = Value; + if (v != null) { string s; - if (Value is IFormattable formattable) + if (v is IFormattable formattable) { s = formattable.ToString(null, Culture); } else { - Uri uri = Value as Uri; - s = uri != null ? uri.OriginalString : Value.ToString(); + Uri uri = v as Uri; + s = uri != null ? uri.OriginalString : v.ToString(); } SetToken(JsonToken.String, s, false); @@ -520,9 +533,9 @@ namespace Newtonsoft.Json { data = CollectionUtils.ArrayEmpty(); } - else if (ConvertUtils.TryConvertGuid(s, out Guid g)) + else if (ConvertUtils.TryConvertGuid(s, out Guid g1)) { - data = g.ToByteArray(); + data = g1.ToByteArray(); } else { @@ -537,9 +550,9 @@ namespace Newtonsoft.Json case JsonToken.EndArray: return null; case JsonToken.Bytes: - if (ValueType == typeof(Guid)) + if (Value is Guid g2) { - byte[] data = ((Guid)Value).ToByteArray(); + byte[] data = g2.ToByteArray(); SetToken(JsonToken.Bytes, data, false); return data; } @@ -606,24 +619,26 @@ namespace Newtonsoft.Json return null; case JsonToken.Integer: case JsonToken.Float: - if (!(Value is double)) + object v = Value; + if (v is double d) { - double d; -#if HAVE_BIG_INTEGER - if (Value is BigInteger value) - { - d = (double)value; - } - else -#endif - { - d = Convert.ToDouble(Value, CultureInfo.InvariantCulture); - } - - SetToken(JsonToken.Float, d, false); + return d; } - return (double)Value; +#if HAVE_BIG_INTEGER + if (v is BigInteger value) + { + d = (double)value; + } + else +#endif + { + d = Convert.ToDouble(v, CultureInfo.InvariantCulture); + } + + SetToken(JsonToken.Float, d, false); + + return (double)d; case JsonToken.String: return ReadDoubleString((string)Value); } @@ -680,7 +695,6 @@ namespace Newtonsoft.Json } SetToken(JsonToken.Boolean, b, false); - return b; case JsonToken.String: return ReadBooleanString((string)Value); @@ -727,24 +741,26 @@ namespace Newtonsoft.Json return null; case JsonToken.Integer: case JsonToken.Float: - if (!(Value is decimal)) + object v = Value; + + if (v is decimal d) { - decimal d; -#if HAVE_BIG_INTEGER - if (Value is BigInteger value) - { - d = (decimal)value; - } - else -#endif - { - d = Convert.ToDecimal(Value, CultureInfo.InvariantCulture); - } - - SetToken(JsonToken.Float, d, false); + return d; } - return (decimal)Value; +#if HAVE_BIG_INTEGER + if (v is BigInteger value) + { + d = (decimal)value; + } + else +#endif + { + d = Convert.ToDecimal(v, CultureInfo.InvariantCulture); + } + + SetToken(JsonToken.Float, d, false); + return d; case JsonToken.String: return ReadDecimalString((string)Value); }