From f32e1f53c58a8023fb647531ccafdbacc11cf4e4 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Mon, 27 Dec 2010 10:06:35 +0000 Subject: [PATCH] -Fixed JToken Load and Parse methods not checking for incomplete content --- Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs | 7 ++ .../Linq/JObjectTests.cs | 75 +++++++++++++++++-- Src/Newtonsoft.Json/Linq/JArray.cs | 5 +- Src/Newtonsoft.Json/Linq/JConstructor.cs | 5 +- Src/Newtonsoft.Json/Linq/JContainer.cs | 15 ++++ Src/Newtonsoft.Json/Linq/JObject.cs | 6 +- Src/Newtonsoft.Json/Linq/JProperty.cs | 5 +- 7 files changed, 95 insertions(+), 23 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs index be77c606..efc2b52f 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs @@ -429,5 +429,12 @@ Parameter name: index")] Assert.AreEqual(1, a.Count); Assert.AreEqual(1, (int)a[0]); } + + [Test] + [ExpectedException(typeof(Exception), ExpectedMessage = "Unexpected end of content while loading JArray.")] + public void ParseIncomplete() + { + JArray.Parse("[1"); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs index 9bbdbf46..0a14d86e 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JObjectTests.cs @@ -464,13 +464,17 @@ Parameter name: arrayIndex")] public void DeserializeClassManually() { string jsonText = @"{ - ""short"":{ - ""original"":""http://www.foo.com/"", - ""short"":""krehqk"", - ""error"":{ - ""code"":0, - ""msg"":""No action taken""} - }"; + ""short"": + { + ""original"":""http://www.foo.com/"", + ""short"":""krehqk"", + ""error"": + { + ""code"":0, + ""msg"":""No action taken"" + } + } +}"; JObject json = JObject.Parse(jsonText); @@ -1490,6 +1494,63 @@ Parameter name: arrayIndex")] JObject.Parse(json); } + [Test] + [ExpectedException(typeof(Exception), ExpectedMessage = "Unexpected end of content while loading JObject.")] + public void ParseIncomplete() + { + JObject.Parse("{ foo:"); + } + + [Test] + public void LoadFromNestedObject() + { + string jsonText = @"{ + ""short"": + { + ""error"": + { + ""code"":0, + ""msg"":""No action taken"" + } + } +}"; + + JsonReader reader = new JsonTextReader(new StringReader(jsonText)); + reader.Read(); + reader.Read(); + reader.Read(); + reader.Read(); + reader.Read(); + + JObject o = (JObject)JToken.ReadFrom(reader); + Assert.IsNotNull(o); + Assert.AreEqual(@"{ + ""code"": 0, + ""msg"": ""No action taken"" +}", o.ToString(Formatting.Indented)); + } + + [Test] + [ExpectedException(typeof(Exception), ExpectedMessage = "Unexpected end of content while loading JObject.")] + public void LoadFromNestedObjectIncomplete() + { + string jsonText = @"{ + ""short"": + { + ""error"": + { + ""code"":0"; + + JsonReader reader = new JsonTextReader(new StringReader(jsonText)); + reader.Read(); + reader.Read(); + reader.Read(); + reader.Read(); + reader.Read(); + + JToken.ReadFrom(reader); + } + #if !SILVERLIGHT [Test] public void GetProperties() diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs index 82708cc6..6b4dc5f1 100644 --- a/Src/Newtonsoft.Json/Linq/JArray.cs +++ b/Src/Newtonsoft.Json/Linq/JArray.cs @@ -111,10 +111,7 @@ namespace Newtonsoft.Json.Linq JArray a = new JArray(); a.SetLineInfo(reader as IJsonLineInfo); - if (!reader.Read()) - throw new Exception("Error reading JArray from JsonReader."); - - a.ReadContentFrom(reader); + a.ReadTokenFrom(reader); return a; } diff --git a/Src/Newtonsoft.Json/Linq/JConstructor.cs b/Src/Newtonsoft.Json/Linq/JConstructor.cs index 296d1ae5..0f8193c4 100644 --- a/Src/Newtonsoft.Json/Linq/JConstructor.cs +++ b/Src/Newtonsoft.Json/Linq/JConstructor.cs @@ -185,10 +185,7 @@ namespace Newtonsoft.Json.Linq JConstructor c = new JConstructor((string)reader.Value); c.SetLineInfo(reader as IJsonLineInfo); - if (!reader.Read()) - throw new Exception("Error reading JConstructor from JsonReader."); - - c.ReadContentFrom(reader); + c.ReadTokenFrom(reader); return c; } diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index b9704a3c..8dd4ca96 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -668,6 +668,21 @@ namespace Newtonsoft.Json.Linq ClearItems(); } + internal void ReadTokenFrom(JsonReader r) + { + int startDepth = r.Depth; + + if (!r.Read()) + throw new Exception("Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); + + ReadContentFrom(r); + + int endDepth = r.Depth; + + if (endDepth > startDepth) + throw new Exception("Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); + } + internal void ReadContentFrom(JsonReader r) { ValidationUtils.ArgumentNotNull(r, "r"); diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 8299dfa7..52741bd6 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -257,6 +257,7 @@ namespace Newtonsoft.Json.Linq if (!reader.Read()) throw new Exception("Error reading JObject from JsonReader."); } + if (reader.TokenType != JsonToken.StartObject) throw new Exception( "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith( @@ -265,10 +266,7 @@ namespace Newtonsoft.Json.Linq JObject o = new JObject(); o.SetLineInfo(reader as IJsonLineInfo); - if (!reader.Read()) - throw new Exception("Error reading JObject from JsonReader."); - - o.ReadContentFrom(reader); + o.ReadTokenFrom(reader); return o; } diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs index d1003888..845ee2fb 100644 --- a/Src/Newtonsoft.Json/Linq/JProperty.cs +++ b/Src/Newtonsoft.Json/Linq/JProperty.cs @@ -260,10 +260,7 @@ namespace Newtonsoft.Json.Linq JProperty p = new JProperty((string)reader.Value); p.SetLineInfo(reader as IJsonLineInfo); - if (!reader.Read()) - throw new Exception("Error reading JProperty from JsonReader."); - - p.ReadContentFrom(reader); + p.ReadTokenFrom(reader); return p; }