using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class MyAttackGadget : IDisposable
static volatile int hackCount;
public static int HackCount { get { return hackCount; } }
public MyAttackGadget(bool suppress)
this.suppress = suppress;
Console.WriteLine("I was constructed!");
protected virtual void Dispose(bool disposing)
Interlocked.Increment(ref hackCount);
GC.SuppressFinalize(this);
public class RootObject<T>
public T Data { get; set; }
public class DataCollection : CollectionBase
public MyData this[int index]
return ((MyData)List[index]);
public int Add(MyData value)
return (List.Add(value));
public int IndexOf(MyData value)
return (List.IndexOf(value));
public void Insert(int index, MyData value)
List.Insert(index, value);
public void Remove(MyData value)
public bool Contains(MyData value)
return (List.Contains(value));
protected override void OnInsert(int index, Object value)
protected override void OnRemove(int index, Object value)
protected override void OnSet(int index, Object oldValue, Object newValue)
protected override void OnValidate(Object value)
if (value.GetType() != typeof(MyData))
throw new ArgumentException("value must be of type MyData.", "value");
public static void Test()
static void TestCollection()
var collection = new DataCollection();
collection.Add(new MyData());
DoTest<DataCollection, DataCollection>(collection, s => s.Replace("MyData", "MyAttackGadget"));
static void TestException()
var exception = new Exception("naughty exception");
exception.Data.Add("foo", new MyAttackGadget(true));
var root = new RootObject<Exception> { Data = exception };
private static void DoTest<T>(T root) where T : class
DoTest<T, T>(root, null);
private static void DoTest<TSerialize, TDeserialize>(TSerialize root, Func<string, string> replace)
where TDeserialize : class
var outputSettings = new JsonSerializerSettings()
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full,
var inputSettings = new JsonSerializerSettings()
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full,
var json = JsonConvert.SerializeObject(root, outputSettings);
var naughtyJson = (replace == null ? json : replace(json));
var hackCount = MyAttackGadget.HackCount;
Console.WriteLine("Deserializing an object of type {0} with the following JSON:", typeof(TDeserialize));
Console.WriteLine(naughtyJson);
var root2 = JsonConvert.DeserializeObject<TDeserialize>(naughtyJson, inputSettings);
Console.WriteLine("Caught expected exception: " + ex.Message);
GC.WaitForPendingFinalizers();
GC.WaitForPendingFinalizers();
if (MyAttackGadget.HackCount > hackCount)
Console.WriteLine("\n**********************I was hacked! Attack successful!**************************");
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
public static void IsTrue(bool value, string message)
throw new AssertionFailedException(message ?? "failed");