From 60cb4ec24064e8c015fb051b0c514098234b5633 Mon Sep 17 00:00:00 2001 From: Dmytro Ohorodniichuk Date: Sat, 2 Jul 2022 17:19:56 +0300 Subject: [PATCH] Issue #1164 Fix unsigned types mapping arithmetic overflow Add tests to reproduce issue #1164 --- Dapper/SqlMapper.cs | 8 +++---- tests/Dapper.Tests/MiscTests.cs | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index fb6ac88e6..61e7e1fe5 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -3788,20 +3788,20 @@ private static void FlexibleConvertBoxedFromHeadOfStack(ILGenerator il, Type fro switch (Type.GetTypeCode(via ?? to)) { case TypeCode.Byte: - opCode = OpCodes.Conv_Ovf_I1_Un; break; + opCode = OpCodes.Conv_Ovf_U1_Un; break; case TypeCode.SByte: opCode = OpCodes.Conv_Ovf_I1; break; case TypeCode.UInt16: - opCode = OpCodes.Conv_Ovf_I2_Un; break; + opCode = OpCodes.Conv_Ovf_U2_Un; break; case TypeCode.Int16: opCode = OpCodes.Conv_Ovf_I2; break; case TypeCode.UInt32: - opCode = OpCodes.Conv_Ovf_I4_Un; break; + opCode = OpCodes.Conv_Ovf_U4_Un; break; case TypeCode.Boolean: // boolean is basically an int, at least at this level case TypeCode.Int32: opCode = OpCodes.Conv_Ovf_I4; break; case TypeCode.UInt64: - opCode = OpCodes.Conv_Ovf_I8_Un; break; + opCode = OpCodes.Conv_Ovf_U8_Un; break; case TypeCode.Int64: opCode = OpCodes.Conv_Ovf_I8; break; case TypeCode.Single: diff --git a/tests/Dapper.Tests/MiscTests.cs b/tests/Dapper.Tests/MiscTests.cs index 24f7bf2bd..7b20f0d3d 100644 --- a/tests/Dapper.Tests/MiscTests.cs +++ b/tests/Dapper.Tests/MiscTests.cs @@ -1286,6 +1286,43 @@ public HazGetOnlyAndCtor(int idProperty, string nameProperty) IdProperty = idProperty; NameProperty = nameProperty; } + } + + [Fact] + public void Issue1164_OverflowExceptionForByte() + { + const string sql = "select cast(200 as smallint) as [value]"; // 200 more than sbyte.MaxValue but less than byte.MaxValue + Issue1164Object obj = connection.QuerySingle>(sql); + Assert.StrictEqual(200, obj.Value); + } + + [Fact] + public void Issue1164_OverflowExceptionForUInt16() + { + const string sql = "select cast(40000 as bigint) as [value]"; // 40000 more than short.MaxValue but less than ushort.MaxValue + Issue1164Object obj = connection.QuerySingle>(sql); + Assert.StrictEqual(40000, obj.Value); + } + + [Fact] + public void Issue1164_OverflowExceptionForUInt32() + { + const string sql = "select cast(4000000000 as bigint) as [value]"; // 4000000000 more than int.MaxValue but less than uint.MaxValue + Issue1164Object obj = connection.QuerySingle>(sql); + Assert.StrictEqual(4000000000, obj.Value); + } + + [Fact] + public void Issue1164_OverflowExceptionForUInt64() + { + const string sql = "select cast(10000000000000000000.0 as float) as [value]"; // 10000000000000000000 more than long.MaxValue but less than ulong.MaxValue + Issue1164Object obj = connection.QuerySingle>(sql); + Assert.StrictEqual(10000000000000000000, obj.Value); + } + + private class Issue1164Object + { + public T Value; } } }