Commit 7eb0c481 authored by mgravell's avatar mgravell

fix 'could destabilise runtime' error if structs threw an error; also tidied...

fix 'could destabilise runtime' error if structs threw an error; also tidied up the locals and made the func return the right type
parent 76b930a4
......@@ -1446,11 +1446,11 @@ static List<FieldInfo> GetSettableFields(Type t)
#endif
)
{
var dm = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), type.IsValueType ? typeof(object) : type, new[] { typeof(IDataReader) }, true);
var dm = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(object), new[] { typeof(IDataReader) }, true);
var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int));
var emptyLocal = il.DeclareLocal(type);
il.DeclareLocal(type);
bool haveEnumLocal = false;
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_0);
......@@ -1484,18 +1484,23 @@ static List<FieldInfo> GetSettableFields(Type t)
int index = startBound;
il.BeginExceptionBlock();
// stack is empty
if (type.IsValueType)
{
il.Emit(OpCodes.Ldloca, emptyLocal);
il.Emit(OpCodes.Ldloca_S, (byte)1);
il.Emit(OpCodes.Initobj, type);
il.Emit(OpCodes.Ldloca, emptyLocal);
}
else
{
il.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
il.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
il.Emit(OpCodes.Stloc_1);
}
il.BeginExceptionBlock();
if(type.IsValueType)
{
il.Emit(OpCodes.Ldloca_S, (byte)1);// [target]
} else
{
il.Emit(OpCodes.Ldloc_1);// [target]
}
// stack is now [target]
......@@ -1640,20 +1645,13 @@ static List<FieldInfo> GetSettableFields(Type t)
il.Emit(OpCodes.Ldloc_0); // stack is Exception, index
il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod("ThrowDataException"), null);
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Stloc_1); // to make it verifiable
il.EndExceptionBlock();
if (type.IsValueType)
il.Emit(OpCodes.Ldloc_1); // stack is [rval]
if(type.IsValueType)
{
il.Emit(OpCodes.Ldloc, emptyLocal); // stack is [rval]
il.Emit(OpCodes.Box, type);
}
else
{
il.Emit(OpCodes.Ldloc_1); // stack is [rval]
}
il.Emit(OpCodes.Ret);
return (Func<IDataReader, object>)dm.CreateDelegate(typeof(Func<IDataReader,object>));
......
......@@ -1192,5 +1192,22 @@ public void TestNullableUniqueIdentifierNull()
var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
result.IsEqualTo(guid);
}
public void TestFailInASaneWayWithWrongStructColumnTypes()
{
try
{
connection.Query<CanHazInt>("select cast(1 as bigint) Value").Single();
throw new Exception("Should not have got here");
} catch(DataException ex)
{
ex.Message.IsEqualTo("Error parsing column 0 (Value=1 - Int64)");
}
}
struct CanHazInt
{
public int Value { get; set; }
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment