Commit 8b49eb69 authored by Joseph Musser's avatar Joseph Musser Committed by Marc Gravell

Stop setting current index local which is nonexistent in ValueTuple deserializer (#1280)

* String and byte[] tuple elements cause InvalidProgramException

* Stop setting current index local which is nonexistent in ValueTuple deserializer
parent fcd8a702
...@@ -98,5 +98,19 @@ public void TupleReturnValue_Works_With15Elements() ...@@ -98,5 +98,19 @@ public void TupleReturnValue_Works_With15Elements()
Assert.Equal(14, val.e14); Assert.Equal(14, val.e14);
Assert.Equal(15, val.e15); Assert.Equal(15, val.e15);
} }
[Fact]
public void TupleReturnValue_Works_WithStringField()
{
var val = connection.QuerySingle<ValueTuple<string>>("select '42'");
Assert.Equal("42", val.Item1);
}
[Fact]
public void TupleReturnValue_Works_WithByteField()
{
var val = connection.QuerySingle<ValueTuple<byte[]>>("select 0xDEADBEEF");
Assert.Equal(new byte[] { 0xDE, 0xAD, 0xBE, 0xEF }, val.Item1);
}
} }
} }
...@@ -3178,7 +3178,7 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea ...@@ -3178,7 +3178,7 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea
private static void GenerateDeserializerFromMap(Type type, IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing, ILGenerator il) private static void GenerateDeserializerFromMap(Type type, IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing, ILGenerator il)
{ {
il.DeclareLocal(typeof(int)); var currentIndexDiagnosticLocal = il.DeclareLocal(typeof(int));
il.DeclareLocal(type); il.DeclareLocal(type);
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Stloc_0);
...@@ -3292,6 +3292,10 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3292,6 +3292,10 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
Label finishLabel = il.DefineLabel(); Label finishLabel = il.DefineLabel();
Type memberType = item.MemberType; Type memberType = item.MemberType;
// Save off the current index for access if an exception is thrown
EmitInt32(il, index);
il.Emit(OpCodes.Stloc, currentIndexDiagnosticLocal);
LoadReaderValueOrBranchToDBNullLabel(il, index, ref enumDeclareLocal, valueCopyLocal, reader.GetFieldType(index), memberType, out var isDbNullLabel); LoadReaderValueOrBranchToDBNullLabel(il, index, ref enumDeclareLocal, valueCopyLocal, reader.GetFieldType(index), memberType, out var isDbNullLabel);
if (specializedConstructor == null) if (specializedConstructor == null)
...@@ -3379,7 +3383,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3379,7 +3383,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
} }
il.MarkLabel(allDone); il.MarkLabel(allDone);
il.BeginCatchBlock(typeof(Exception)); // stack is Exception il.BeginCatchBlock(typeof(Exception)); // stack is Exception
il.Emit(OpCodes.Ldloc_0); // stack is Exception, index il.Emit(OpCodes.Ldloc, currentIndexDiagnosticLocal); // stack is Exception, index
il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader
LoadLocal(il, valueCopyLocal); // stack is Exception, index, reader, value LoadLocal(il, valueCopyLocal); // stack is Exception, index, reader, value
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod(nameof(SqlMapper.ThrowDataException)), null); il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod(nameof(SqlMapper.ThrowDataException)), null);
...@@ -3413,8 +3417,6 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind ...@@ -3413,8 +3417,6 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind
isDbNullLabel = il.DefineLabel(); isDbNullLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_0); // stack is now [...][reader] il.Emit(OpCodes.Ldarg_0); // stack is now [...][reader]
EmitInt32(il, index); // stack is now [...][reader][index] EmitInt32(il, index); // stack is now [...][reader][index]
il.Emit(OpCodes.Dup);// stack is now [...][reader][index][index]
il.Emit(OpCodes.Stloc_0);// stack is now [...][reader][index]
il.Emit(OpCodes.Callvirt, getItem); // stack is now [...][value-as-object] il.Emit(OpCodes.Callvirt, getItem); // stack is now [...][value-as-object]
if (valueCopyLocal != null) if (valueCopyLocal != null)
......
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