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) ...@@ -1446,11 +1446,11 @@ static List<FieldInfo> GetSettableFields(Type t)
#endif #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(); var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int)); il.DeclareLocal(typeof(int));
var emptyLocal = il.DeclareLocal(type); il.DeclareLocal(type);
bool haveEnumLocal = false; bool haveEnumLocal = false;
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Stloc_0);
...@@ -1484,18 +1484,23 @@ static List<FieldInfo> GetSettableFields(Type t) ...@@ -1484,18 +1484,23 @@ static List<FieldInfo> GetSettableFields(Type t)
int index = startBound; int index = startBound;
il.BeginExceptionBlock();
// stack is empty
if (type.IsValueType) if (type.IsValueType)
{ {
il.Emit(OpCodes.Ldloca, emptyLocal); il.Emit(OpCodes.Ldloca_S, (byte)1);
il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Initobj, type);
il.Emit(OpCodes.Ldloca, emptyLocal);
} }
else 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] // stack is now [target]
...@@ -1640,20 +1645,13 @@ static List<FieldInfo> GetSettableFields(Type t) ...@@ -1640,20 +1645,13 @@ static List<FieldInfo> GetSettableFields(Type t)
il.Emit(OpCodes.Ldloc_0); // stack is Exception, index il.Emit(OpCodes.Ldloc_0); // stack is Exception, index
il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod("ThrowDataException"), null); il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod("ThrowDataException"), null);
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Stloc_1); // to make it verifiable
il.EndExceptionBlock(); il.EndExceptionBlock();
il.Emit(OpCodes.Ldloc_1); // stack is [rval]
if (type.IsValueType) if(type.IsValueType)
{ {
il.Emit(OpCodes.Ldloc, emptyLocal); // stack is [rval]
il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Box, type);
} }
else
{
il.Emit(OpCodes.Ldloc_1); // stack is [rval]
}
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
return (Func<IDataReader, object>)dm.CreateDelegate(typeof(Func<IDataReader,object>)); return (Func<IDataReader, object>)dm.CreateDelegate(typeof(Func<IDataReader,object>));
......
...@@ -1192,5 +1192,22 @@ public void TestNullableUniqueIdentifierNull() ...@@ -1192,5 +1192,22 @@ public void TestNullableUniqueIdentifierNull()
var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single(); var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
result.IsEqualTo(guid); 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