From c9cfff4fedb82692f486706d067b4aeb702ef217 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 23 Jan 2017 15:07:16 +1300 Subject: [PATCH] -Changed exception thrown when parsing invalid Unicode escape sequence to JsonReaderException --- .../JsonTextReaderTests/MiscAsyncTests.cs | 13 +++++ .../JsonTextReaderTests/MiscTests.cs | 13 +++++ .../Utilities/ConvertUtilsTests.cs | 16 ++++--- Src/Newtonsoft.Json/JsonTextReader.cs | 16 +++++-- Src/Newtonsoft.Json/Utilities/ConvertUtils.cs | 47 ++++++++++--------- 5 files changed, 72 insertions(+), 33 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscAsyncTests.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscAsyncTests.cs index a05893b9..138fd8ee 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscAsyncTests.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscAsyncTests.cs @@ -983,6 +983,19 @@ null//comment Assert.IsFalse(await r.ReadAsync()); } + + [Test] + public async Task InvalidUnicodeSequence() + { + string json1 = @"{'prop':'\u123!'}"; + + JsonTextReader r = new JsonTextReader(new StringReader(json1)); + + Assert.IsTrue(await r.ReadAsync()); + Assert.IsTrue(await r.ReadAsync()); + + await ExceptionAssert.ThrowsAsync(async () => { await r.ReadAsync(); }, @"Invalid Unicode escape sequence: \u123!. Path 'prop', line 1, position 11."); + } #endif } } diff --git a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscTests.cs b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscTests.cs index 19bb5206..46242dbb 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscTests.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextReaderTests/MiscTests.cs @@ -1029,5 +1029,18 @@ null//comment GC.WaitForPendingFinalizers(); Assert.AreEqual(1, UnmanagedResourceFakingJsonReader.DisposalCalls); } + + [Test] + public void InvalidUnicodeSequence() + { + string json1 = @"{'prop':'\u123!'}"; + + JsonTextReader r = new JsonTextReader(new StringReader(json1)); + + Assert.IsTrue(r.Read()); + Assert.IsTrue(r.Read()); + + ExceptionAssert.Throws(() => { r.Read(); }, @"Invalid Unicode escape sequence: \u123!. Path 'prop', line 1, position 11."); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Utilities/ConvertUtilsTests.cs b/Src/Newtonsoft.Json.Tests/Utilities/ConvertUtilsTests.cs index 3bb476cc..ea0c77d3 100644 --- a/Src/Newtonsoft.Json.Tests/Utilities/ConvertUtilsTests.cs +++ b/Src/Newtonsoft.Json.Tests/Utilities/ConvertUtilsTests.cs @@ -269,25 +269,27 @@ namespace Newtonsoft.Json.Tests.Utilities [Test] public void HexParseOffset() { - int value = ConvertUtils.HexTextToInt("!0000".ToCharArray(), 1, 5); + int value; + Assert.IsTrue(ConvertUtils.TryHexTextToInt("!0000".ToCharArray(), 1, 5, out value)); Assert.AreEqual(0, value); } [Test] public void HexParseError() { - ExceptionAssert.Throws(() => { ConvertUtils.HexTextToInt("-100".ToCharArray(), 0, 4); }, "Invalid hex character: -"); - ExceptionAssert.Throws(() => { ConvertUtils.HexTextToInt("000g".ToCharArray(), 0, 4); }, "Invalid hex character: g"); - ExceptionAssert.Throws(() => { ConvertUtils.HexTextToInt(" ssd".ToCharArray(), 0, 4); }, "Invalid hex character: "); - ExceptionAssert.Throws(() => { ConvertUtils.HexTextToInt("000:".ToCharArray(), 0, 4); }, "Invalid hex character: :"); - ExceptionAssert.Throws(() => { ConvertUtils.HexTextToInt("000G".ToCharArray(), 0, 4); }, "Invalid hex character: G"); + int value; + Assert.IsFalse(ConvertUtils.TryHexTextToInt("-100".ToCharArray(), 0, 4, out value)); + Assert.IsFalse(ConvertUtils.TryHexTextToInt(" ssd".ToCharArray(), 0, 4, out value)); + Assert.IsFalse(ConvertUtils.TryHexTextToInt("000:".ToCharArray(), 0, 4, out value)); + Assert.IsFalse(ConvertUtils.TryHexTextToInt("000G".ToCharArray(), 0, 4, out value)); } private void HexParseSame(string text) { int v1 = int.Parse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture); - int v2 = ConvertUtils.HexTextToInt(text.ToCharArray(), 0, 4); + int v2; + Assert.IsTrue(ConvertUtils.TryHexTextToInt(text.ToCharArray(), 0, 4, out v2)); Assert.AreEqual(v1, v2, "Invalid result when parsing hex text: " + text); } diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index f33ce6d9..f001214b 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -1261,13 +1261,21 @@ namespace Newtonsoft.Json { if (enoughChars) { - char hexChar = Convert.ToChar(ConvertUtils.HexTextToInt(_chars, _charPos, _charPos + 4)); - _charPos += 4; - return hexChar; + int value; + if (ConvertUtils.TryHexTextToInt(_chars, _charPos, _charPos + 4, out value)) + { + char hexChar = Convert.ToChar(value); + _charPos += 4; + return hexChar; + } + else + { + throw JsonReaderException.Create(this, @"Invalid Unicode escape sequence: \u{0}.".FormatWith(CultureInfo.InvariantCulture, new string(_chars, _charPos, 4))); + } } else { - throw JsonReaderException.Create(this, "Unexpected end while parsing Unicode character."); + throw JsonReaderException.Create(this, "Unexpected end while parsing Unicode escape sequence."); } } diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs index fb2eb8a4..413ff0a3 100644 --- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -1381,34 +1381,37 @@ namespace Newtonsoft.Json.Utilities #endif } - public static int HexTextToInt(char[] text, int start, int end) + public static bool TryHexTextToInt(char[] text, int start, int end, out int value) { - int value = 0; + value = 0; + for (int i = start; i < end; i++) { - value += HexCharToInt(text[i]) << ((end - 1 - i) * 4); - } - return value; - } + char ch = text[i]; + int chValue; - private static int HexCharToInt(char ch) - { - if (ch <= 57 && ch >= 48) - { - return ch - 48; + if (ch <= 57 && ch >= 48) + { + chValue = ch - 48; + } + else if (ch <= 70 && ch >= 65) + { + chValue = ch - 55; + } + else if (ch <= 102 && ch >= 97) + { + chValue = ch - 87; + } + else + { + value = 0; + return false; + } + + value += chValue << ((end - 1 - i) * 4); } - if (ch <= 70 && ch >= 65) - { - return ch - 55; - } - - if (ch <= 102 && ch >= 97) - { - return ch - 87; - } - - throw new FormatException("Invalid hex character: " + ch); + return true; } } } \ No newline at end of file