Correcting some invalid array json inputs (dotnet/corefx#38323)
authorAnirudh Agnihotry <anirudhagnihotry098@gmail.com>
Thu, 13 Jun 2019 22:10:13 +0000 (15:10 -0700)
committerGitHub <noreply@github.com>
Thu, 13 Jun 2019 22:10:13 +0000 (15:10 -0700)
* correcting some invalid array json inputs

* adding comments and modifiers

* addressing feedback

* correcting issue number

Commit migrated from https://github.com/dotnet/corefx/commit/eaee16b5c9d3e020b5892a28a204ceb5da4d6a4a

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullable.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleArray.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleDictionary.cs
src/libraries/System.Text.Json/tests/Serialization/DictionaryTests.cs

index 07920e8..9914128 100644 (file)
@@ -52,12 +52,20 @@ namespace System.Text.Json
         {
             Debug.Assert(ShouldDeserialize);
 
+            // We need a property in order to a apply a value in a dictionary.
             if (state.Current.KeyName == null && (state.Current.IsProcessingDictionary || state.Current.IsProcessingImmutableDictionary))
             {
                 ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(RuntimePropertyType, reader, state.JsonPath);
                 return;
             }
 
+            // We need an initialized array in order to store the values.
+            if (state.Current.IsProcessingEnumerable && state.Current.TempEnumerableValues == null && state.Current.ReturnValue == null)
+            {
+                ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(RuntimePropertyType, reader, state.JsonPath);
+                return;
+            }
+
             if (ValueConverter == null || !ValueConverter.TryRead(RuntimePropertyType, ref reader, out TRuntimeProperty value))
             {
                 ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(RuntimePropertyType, reader, state.JsonPath);
index 95cc63e..7ee0975 100644 (file)
@@ -162,7 +162,12 @@ namespace System.Text.Json
                 }
                 else
                 {
-                    ((IList)state.Current.ReturnValue).Add(value);
+                    if (!(state.Current.ReturnValue is IList list))
+                    {
+                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(value.GetType(), reader, state.JsonPath);
+                        return;
+                    }
+                    list.Add(value);
                 }
             }
             else if (!setPropertyDirectly && state.Current.IsEnumerableProperty)
index c1eae71..9c7f73d 100644 (file)
@@ -46,6 +46,11 @@ namespace System.Text.Json
                 }
                 else
                 {
+                    if (classInfo.CreateObject == null)
+                    {
+                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type, reader, state.JsonPath);
+                        return;
+                    }
                     state.Current.ReturnValue = classInfo.CreateObject();
                 }
                 return;
index c845e4b..fbe5a18 100644 (file)
@@ -124,12 +124,34 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Throws<JsonException>(() => JsonSerializer.Parse(json, type));
         }
 
+        [Theory]
+        [InlineData(typeof(int[]), @"""test""")]
+        [InlineData(typeof(int[]), @"1")]
+        [InlineData(typeof(int[]), @"false")]
+        [InlineData(typeof(int[]), @"{}")]
+        [InlineData(typeof(int[]), @"[""test""")]
+        [InlineData(typeof(int[]), @"[true]")]
+        // [InlineData(typeof(int[]), @"[{}]")] TODO #38485: Uncomment when fixed
+        [InlineData(typeof(int[]), @"[[]]")]
+        [InlineData(typeof(Dictionary<string, int[]>), @"{""test"": {}}")]
+        [InlineData(typeof(Dictionary<string, int[]>), @"{""test"": ""test""}")]
+        [InlineData(typeof(Dictionary<string, int[]>), @"{""test"": 1}")]
+        [InlineData(typeof(Dictionary<string, int[]>), @"{""test"": true}")]
+        [InlineData(typeof(Dictionary<string, int[]>), @"{""test"": [""test""]}")]
+        [InlineData(typeof(Dictionary<string, int[]>), @"{""test"": [[]]}")]
+        // [InlineData(typeof(Dictionary<string, int[]>), @"{""test"": [{}]}")] TODO #38485: Uncomment when fixed
+        public static void InvalidJsonForArrayShouldFail(Type type, string json)
+        {
+            Assert.Throws<JsonException>(() => JsonSerializer.Parse(json, type));
+        }
+
         [Fact]
         public static void InvalidEmptyDictionaryInput()
         {
             Assert.Throws<JsonException>(() => JsonSerializer.Parse<string>("{}"));
         }
 
+        [Fact]
         public static void PocoWithDictionaryObject()
         {
             PocoDictionary dict = JsonSerializer.Parse<PocoDictionary>("{\n\t\"key\" : {\"a\" : \"b\", \"c\" : \"d\"}}");
@@ -137,7 +159,7 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(dict.key["c"], "d");
         }
 
-        class PocoDictionary
+        public class PocoDictionary
         {
             public Dictionary<string, string> key { get; set; }
         }
@@ -160,7 +182,7 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(@"{""Id"":10}", element.ToString());
         }
 
-        class Poco
+        public class Poco
         {
             public int Id { get; set; }
         }