diff --git a/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs index cd79de50..83763912 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/DataSetConverterTests.cs @@ -41,6 +41,13 @@ namespace Newtonsoft.Json.Tests.Converters { public class DataSetConverterTests : TestFixtureBase { + [Test] + public void DeserializeInvalidDataTable() + { + ExceptionAssert.Throws("Unexpected JSON token when reading DataTable. Expected StartArray, got Integer. Path 'pending_count', line 1, position 19.", + () => JsonConvert.DeserializeObject("{\"pending_count\":23,\"completed_count\":45}")); + } + [Test] public void SerializeAndDeserialize() { diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 6015a361..a8134a7b 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -7892,6 +7892,18 @@ Parameter name: value", } #endif + [Test] + public void DuplicatePropertiesInNestedObject() + { + ExceptionAssert.Throws( + "Can not add property time to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.", + () => + { + string content = @"{""result"":{""time"":1408188592,""time"":1408188593},""error"":null,""id"":""1""}"; + JsonConvert.DeserializeObject(content); + }); + } + [Test] public void RoundtripUriOriginalString() { diff --git a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs index 5361a55c..3bfffffc 100644 --- a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs @@ -77,7 +77,7 @@ namespace Newtonsoft.Json.Converters DataTableConverter converter = new DataTableConverter(); - reader.Read(); + CheckedRead(reader); while (reader.TokenType == JsonToken.PropertyName) { @@ -89,7 +89,7 @@ namespace Newtonsoft.Json.Converters if (!exists) ds.Tables.Add(dt); - reader.Read(); + CheckedRead(reader); } return ds; @@ -106,6 +106,12 @@ namespace Newtonsoft.Json.Converters { return typeof(DataSet).IsAssignableFrom(valueType); } + + private void CheckedRead(JsonReader reader) + { + if (!reader.Read()) + throw JsonSerializationException.Create(reader, "Unexpected end when reading DataSet."); + } } } diff --git a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs index 774cd894..82d31436 100644 --- a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs @@ -92,17 +92,19 @@ namespace Newtonsoft.Json.Converters { dt.TableName = (string)reader.Value; - reader.Read(); + CheckedRead(reader); } - if (reader.TokenType == JsonToken.StartArray) - reader.Read(); + if (reader.TokenType != JsonToken.StartArray) + throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); + + CheckedRead(reader); while (reader.TokenType != JsonToken.EndArray) { CreateRow(reader, dt); - reader.Read(); + CheckedRead(reader); } return dt; @@ -111,13 +113,13 @@ namespace Newtonsoft.Json.Converters private static void CreateRow(JsonReader reader, DataTable dt) { DataRow dr = dt.NewRow(); - reader.Read(); + CheckedRead(reader); while (reader.TokenType == JsonToken.PropertyName) { string columnName = (string)reader.Value; - reader.Read(); + CheckedRead(reader); DataColumn column = dt.Columns[columnName]; if (column == null) @@ -130,7 +132,7 @@ namespace Newtonsoft.Json.Converters if (column.DataType == typeof(DataTable)) { if (reader.TokenType == JsonToken.StartArray) - reader.Read(); + CheckedRead(reader); DataTable nestedDt = new DataTable(); @@ -138,7 +140,7 @@ namespace Newtonsoft.Json.Converters { CreateRow(reader, nestedDt); - reader.Read(); + CheckedRead(reader); } dr[columnName] = nestedDt; @@ -146,14 +148,14 @@ namespace Newtonsoft.Json.Converters else if (column.DataType.IsArray && column.DataType != typeof(byte[])) { if (reader.TokenType == JsonToken.StartArray) - reader.Read(); + CheckedRead(reader); List o = new List(); while (reader.TokenType != JsonToken.EndArray) { o.Add(reader.Value); - reader.Read(); + CheckedRead(reader); } Array destinationArray = Array.CreateInstance(column.DataType.GetElementType(), o.Count); @@ -165,8 +167,8 @@ namespace Newtonsoft.Json.Converters { dr[columnName] = reader.Value ?? DBNull.Value; } - - reader.Read(); + + CheckedRead(reader); } dr.EndEdit(); @@ -190,17 +192,23 @@ namespace Newtonsoft.Json.Converters case JsonToken.Undefined: return typeof(string); case JsonToken.StartArray: - reader.Read(); + CheckedRead(reader); if (reader.TokenType == JsonToken.StartObject) return typeof(DataTable); // nested datatable Type arrayType = GetColumnDataType(reader); return arrayType.MakeArrayType(); default: - throw new JsonException("Unexpected JSON token while reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType)); + throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType)); } } + private static void CheckedRead(JsonReader reader) + { + if (!reader.Read()) + throw JsonSerializationException.Create(reader, "Unexpected end when reading DataTable."); + } + /// /// Determines whether this instance can convert the specified value type. /// diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs index ff1fb543..0973319b 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -155,9 +155,11 @@ namespace Newtonsoft.Json.Linq /// The name of the property. public override void WritePropertyName(string name) { - base.WritePropertyName(name); - AddParent(new JProperty(name)); + + // don't set state until after in case of an error such as duplicate property names + // incorrect state will cause issues if writer is disposed when closing open properties + base.WritePropertyName(name); } private void AddValue(object value, JsonToken token)