From 9352d4867843a84f584f4527acde216431823499 Mon Sep 17 00:00:00 2001 From: Alisha Kim Date: Sun, 17 Dec 2023 20:03:18 +0900 Subject: [PATCH] Fixed packet corruption issue when enum was not 4 bytes. Signed-off-by: Alisha Kim --- src/MySqlConnector/MySqlParameter.cs | 40 ++++++++++++++- tests/MySqlConnector.Tests/DummyEnum.cs | 50 ++++++++++++++++++- .../MySqlConnector.Tests.csproj | 2 +- .../MySqlParameterAppendBinaryTests.cs | 27 ++++++++++ 4 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 tests/MySqlConnector.Tests/MySqlParameterAppendBinaryTests.cs diff --git a/src/MySqlConnector/MySqlParameter.cs b/src/MySqlConnector/MySqlParameter.cs index 841051780..34100b5bd 100644 --- a/src/MySqlConnector/MySqlParameter.cs +++ b/src/MySqlConnector/MySqlParameter.cs @@ -835,7 +835,45 @@ internal void AppendBinary(ByteBufferWriter writer, StatementPreparerOptions opt } else if (Value is Enum) { - writer.Write(Convert.ToInt32(Value, CultureInfo.InvariantCulture)); + var enumType = Value.GetType(); + var enumUnderlyingType = enumType.GetEnumUnderlyingType(); + + if (enumUnderlyingType == typeof(byte)) + { + writer.Write((byte) Value); + } + else if (enumUnderlyingType == typeof(sbyte)) + { + writer.Write(unchecked((byte) (sbyte) Value)); + } + else if (enumUnderlyingType == typeof(short)) + { + writer.Write(unchecked((ushort) (short) Value)); + } + else if (enumUnderlyingType == typeof(ushort)) + { + writer.Write((ushort) Value); + } + else if (enumUnderlyingType == typeof(int)) + { + writer.Write((int) Value); + } + else if (enumUnderlyingType == typeof(uint)) + { + writer.Write((uint) Value); + } + else if (enumUnderlyingType == typeof(long)) + { + writer.Write(unchecked((ulong) (long) Value)); + } + else if (enumUnderlyingType == typeof(ulong)) + { + writer.Write((ulong) Value); + } + else + { + throw new NotSupportedException($"Parameter type {Value.GetType().Name} is not supported; see https://fl.vu/mysql-param-type. Value: {Value}"); + } } else if (MySqlDbType == MySqlDbType.Int16) { diff --git a/tests/MySqlConnector.Tests/DummyEnum.cs b/tests/MySqlConnector.Tests/DummyEnum.cs index 70b580905..627e5e0c1 100644 --- a/tests/MySqlConnector.Tests/DummyEnum.cs +++ b/tests/MySqlConnector.Tests/DummyEnum.cs @@ -4,4 +4,52 @@ internal enum DummyEnum { FirstValue, SecondValue -} +} + +internal enum DummyByteEnum : byte +{ + FirstValue, + SecondValue = 0x11, +} + +internal enum DummySByteEnum : sbyte +{ + FirstValue, + SecondValue = 0x11, +} + +internal enum DummyShortEnum : short +{ + FirstValue, + SecondValue = 0x1122, +} + +internal enum DummyUShortEnum : ushort +{ + FirstValue, + SecondValue = 0x1122, +} + +internal enum DummyIntEnum : int +{ + FirstValue, + SecondValue = 0x11223344, +} + +internal enum DummyUIntEnum : uint +{ + FirstValue, + SecondValue = 0x11223344, +} + +internal enum DummyLongEnum : long +{ + FirstValue, + SecondValue = 0x11223344_55667788, +} + +internal enum DummyULongEnum : ulong +{ + FirstValue, + SecondValue = 0x11223344_55667788, +} diff --git a/tests/MySqlConnector.Tests/MySqlConnector.Tests.csproj b/tests/MySqlConnector.Tests/MySqlConnector.Tests.csproj index 8eddd9566..fed6d961c 100644 --- a/tests/MySqlConnector.Tests/MySqlConnector.Tests.csproj +++ b/tests/MySqlConnector.Tests/MySqlConnector.Tests.csproj @@ -47,7 +47,7 @@ - + diff --git a/tests/MySqlConnector.Tests/MySqlParameterAppendBinaryTests.cs b/tests/MySqlConnector.Tests/MySqlParameterAppendBinaryTests.cs new file mode 100644 index 000000000..948332773 --- /dev/null +++ b/tests/MySqlConnector.Tests/MySqlParameterAppendBinaryTests.cs @@ -0,0 +1,27 @@ +using MySqlConnector.Protocol.Serialization; + +namespace MySqlConnector.Tests; + +public class MySqlParameterAppendBinaryTests +{ + [Theory] + [InlineData(DummySByteEnum.SecondValue, MySqlDbType.Byte, new byte[] { 0x11 })] + [InlineData(DummyByteEnum.SecondValue, MySqlDbType.UByte, new byte[] { 0x11 })] + [InlineData(DummyShortEnum.SecondValue, MySqlDbType.Int16, new byte[] { 0x22, 0x11 })] + [InlineData(DummyUShortEnum.SecondValue, MySqlDbType.UInt16, new byte[] { 0x22, 0x11 })] + [InlineData(DummyIntEnum.SecondValue, MySqlDbType.Int32, new byte[] { 0x44, 0x33, 0x22, 0x11 })] + [InlineData(DummyUIntEnum.SecondValue, MySqlDbType.UInt32, new byte[] { 0x44, 0x33, 0x22, 0x11 })] + [InlineData(DummyEnum.SecondValue, MySqlDbType.Int32, new byte[] { 0x01, 0x00, 0x00, 0x00 })] + [InlineData(DummyLongEnum.SecondValue, MySqlDbType.Int64, new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 })] + [InlineData(DummyULongEnum.SecondValue, MySqlDbType.UInt64, new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 })] + public void WriteBinaryEnumType(object value, MySqlDbType expectedMySqlDbType, byte[] expectedBinary) + { + var parameter = new MySqlParameter { Value = value }; + var writer = new ByteBufferWriter(); + parameter.AppendBinary(writer, StatementPreparerOptions.None); + + Assert.Equal(parameter.MySqlDbType, expectedMySqlDbType); + Assert.Equal(writer.Position, expectedBinary.Length); + Assert.Equal(writer.ArraySegment, expectedBinary); + } +}