From 55a09d2f735f7ac32fdd0379eb8530377bd8234d Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 14 Jul 2012 11:56:38 +1200 Subject: [PATCH] -Handle partial trust when creating uninitialized objects --- .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/JsonSerializerTest.cs | 45 +++++++++++++++++-- .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/DefaultContractResolver.cs | 6 ++- .../Serialization/JsonObjectContract.cs | 8 ++++ .../JsonSerializerInternalWriter.cs | 3 +- 6 files changed, 57 insertions(+), 9 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index f9df0c04..1c1936a6 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -72,5 +72,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.7.15110")] +[assembly: AssemblyFileVersion("4.5.7.15114")] #endif diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index de15507e..3f16b678 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -6540,6 +6540,22 @@ Parameter name: value", } } + [JsonObject(MemberSerialization.Fields)] + public class MyTuplePartial + { + private readonly T1 m_Item1; + + public MyTuplePartial(T1 item1) + { + m_Item1 = item1; + } + + public T1 Item1 + { + get { return m_Item1; } + } + } + [Test] public void SerializeCustomTupleWithSerializableAttribute() { @@ -6550,9 +6566,9 @@ Parameter name: value", MyTuple obj = null; Action doStuff = () => - { - obj = JsonConvert.DeserializeObject>(json); - }; + { + obj = JsonConvert.DeserializeObject>(json); + }; #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) doStuff(); @@ -6564,6 +6580,29 @@ Parameter name: value", #endif } +#if DEBUG + [Test] + public void SerializeCustomTupleWithSerializableAttributeInPartialTrust() + { + try + { + JsonTypeReflector.SetFullyTrusted(false); + + var tuple = new MyTuplePartial(500); + var json = JsonConvert.SerializeObject(tuple); + Assert.AreEqual(@"{""m_Item1"":500}", json); + + ExceptionAssert.Throws( + "Unable to find a constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+MyTuplePartial`1[System.Int32]. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'm_Item1', line 1, position 11.", + () => JsonConvert.DeserializeObject>(json)); + } + finally + { + JsonTypeReflector.SetFullyTrusted(true); + } + } +#endif + #if !(SILVERLIGHT || NETFX_CORE || PORTABLE || NET35 || NET20) [Test] public void SerializeTupleWithSerializableAttribute() diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 86250245..7682ed79 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -90,7 +90,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.7.15110")] +[assembly: AssemblyFileVersion("4.5.7.15114")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 2f7a0ecc..5f9a04a7 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -375,8 +375,10 @@ namespace Newtonsoft.Json.Serialization else if (contract.MemberSerialization == MemberSerialization.Fields) { #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) - // mimic DataContractSerializer behaviour and create uninitialized object when populating fields - contract.DefaultCreator = contract.GetUninitializedObject; + // mimic DataContractSerializer behaviour when populating fields by overriding default creator to create an uninitialized object + // note that this is only possible when the application is fully trusted so fall back to using the default constructor (if available) in partial trust + if (JsonTypeReflector.FullyTrusted) + contract.DefaultCreator = contract.GetUninitializedObject; #endif } else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic) diff --git a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs index 05196f1c..0a4806d3 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs @@ -24,9 +24,11 @@ #endregion using System; +using System.Globalization; using System.Reflection; using System.Runtime.Serialization; using System.Security; +using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Serialization { @@ -118,9 +120,15 @@ namespace Newtonsoft.Json.Serialization } #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) +#if !(NET20 || NET35) [SecuritySafeCritical] +#endif internal object GetUninitializedObject() { + // we should never get here if the environment is not fully trusted, check just in case + if (!JsonTypeReflector.FullyTrusted) + throw new JsonException("Insufficient permissions. Creating an uninitialized '{0}' type requires full trust.".FormatWith(CultureInfo.InvariantCulture, NonNullableUnderlyingType)); + return FormatterServices.GetUninitializedObject(NonNullableUnderlyingType); } #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 0beff5ec..196a12f9 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -512,8 +512,7 @@ namespace Newtonsoft.Json.Serialization } #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) -#if !NET20 - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Security.SecuritySafeCriticalAttribute")] +#if !(NET20 || NET35) [SecuritySafeCritical] #endif private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)