Use MaxExpansionFactorWhileTranscoding instead of counting bytes (#478)
authorKristian Hellang <kristian@hellang.com>
Fri, 6 Dec 2019 01:41:21 +0000 (02:41 +0100)
committerAhson Khan <ahson_ahmedk@yahoo.com>
Fri, 6 Dec 2019 01:41:21 +0000 (17:41 -0800)
src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs
src/libraries/System.Text.Json/tests/JsonDateTimeTestData.cs
src/libraries/System.Text.Json/tests/JsonStringTests.cs

index 71ec914..978640c 100644 (file)
@@ -50,13 +50,13 @@ namespace System.Text.Json
                 return false;
             }
 
-            int length = JsonReaderHelper.GetUtf8ByteCount(source);
+            int maxLength = checked(source.Length * JsonConstants.MaxExpansionFactorWhileTranscoding);
 
-            Span<byte> bytes = length <= JsonConstants.StackallocThreshold
+            Span<byte> bytes = maxLength <= JsonConstants.StackallocThreshold
                 ? stackalloc byte[JsonConstants.StackallocThreshold]
-                : new byte[length];
+                : new byte[maxLength];
 
-            JsonReaderHelper.GetUtf8FromText(source, bytes);
+            int length = JsonReaderHelper.GetUtf8FromText(source, bytes);
 
             return TryParseAsISO(bytes.Slice(0, length), out value);
         }
@@ -69,13 +69,13 @@ namespace System.Text.Json
                 return false;
             }
 
-            int length = JsonReaderHelper.GetUtf8ByteCount(source);
+            int maxLength = checked(source.Length * JsonConstants.MaxExpansionFactorWhileTranscoding);
 
-            Span<byte> bytes = length <= JsonConstants.StackallocThreshold
+            Span<byte> bytes = maxLength <= JsonConstants.StackallocThreshold
                 ? stackalloc byte[JsonConstants.StackallocThreshold]
-                : new byte[length];
+                : new byte[maxLength];
 
-            JsonReaderHelper.GetUtf8FromText(source, bytes);
+            int length = JsonReaderHelper.GetUtf8FromText(source, bytes);
 
             return TryParseAsISO(bytes.Slice(0, length), out value);
         }
index 15e5b4d..7ff20c7 100644 (file)
@@ -229,6 +229,10 @@ namespace System.Text.Json.Tests
             yield return new object[] { "\"199\\u0037-07\\u002d16T1\\u0039:20:30.4555555+\\u002dZ\"" };
             // Proper format but invalid calendar date, time, or time zone designator fields 1997-00-16
             yield return new object[] { "\"\\u0031\\u0039\\u0039\\u0037\\u002d\\u0030\\u0030\\u002d\\u0031\\u0036\"" };
+
+            // High byte expansion - parsing fails early at 254 characters.
+            yield return new object[] { "\"" + new string('\u20AC', 250) + "\"" };
+            yield return new object[] { "\"" + new string('\u20AC', 260) + "\"" };
         }
 
         public static IEnumerable<object[]> DateTimeFractionTrimBaseTests()
index b1ade10..0342ded 100644 (file)
@@ -110,6 +110,21 @@ namespace System.Text.Json.Tests
             Assert.Equal(dateTimeOffset, dateTimeOffset2);
         }
 
+        [Theory]
+        [MemberData(nameof(JsonDateTimeTestData.InvalidISO8601Tests), MemberType = typeof(JsonDateTimeTestData))]
+        public static void TestInvalidDateTime(string testStr)
+        {
+            var jsonString = new JsonString(testStr);
+
+            Assert.False(jsonString.TryGetDateTime(out DateTime dateTimeVal));
+            Assert.Equal(default, dateTimeVal);
+            Assert.False(jsonString.TryGetDateTimeOffset(out DateTimeOffset dateTimeOffsetVal));
+            Assert.Equal(default, dateTimeOffsetVal);
+
+            Assert.Throws<FormatException>(() => jsonString.GetDateTime());
+            Assert.Throws<FormatException>(() => jsonString.GetDateTimeOffset());
+        }
+
         [Fact]
         public static void TestChangingValue()
         {