Bug #84701 Overflow Exception - 64 bit enum value as parameter cast to Int32
Submitted: 28 Jan 2017 18:22 Modified: 24 Nov 2020 16:42
Reporter: Tim Wilkens Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S3 (Non-critical)
Version:6.9.9 OS:Windows
Assigned to: Assigned Account CPU Architecture:Any

[28 Jan 2017 18:22] Tim Wilkens
Description:
== What I Did ==

Pass an Enum value of underlying type ulong that is greater than 2^32 as a parameter to a query.

== What I Expected == 

Query executes returning expected data.

== What Happened ==

Connector throws an OverflowException and does not execute the query.

How to repeat:
See the following test program to observe the behavior. You will need to update the connection string to a mysql server instance you have access to. (Note: the content of the query should not matter since this throws an exception serializing the parameter and never sends it to the server)

using System;
using MySql.Data.MySqlClient;

namespace ConsoleApplication {
    class Program {
        public enum TestEnum : ulong {
            Value = ulong.MaxValue,
        }
        static void Main(string[] args) {
            string connStr = "";
            MySqlConnection conn = new MySqlConnection(connStr);
            try {
                conn.Open();
                string sql = "select * from test where id = @ID;";
                MySqlCommand command = new MySqlCommand(sql, conn);
                command.Parameters.AddWithValue("@ID", TestEnum.Value);
                MySqlDataReader rdr = command.ExecuteReader();
            } catch(Exception e) {
                Console.WriteLine(e);
            }
            conn.Close();
        }
    }
}

Building and running that should produce the following exception:

System.OverflowException: Value was either too large or too small for an Int32.
   at System.Convert.ToInt32(UInt64 value)
   at System.UInt64.System.IConvertible.ToInt32(IFormatProvider provider)
   at System.Convert.ToInt32(Object value, IFormatProvider provider)
   at System.Enum.System.IConvertible.ToInt32(IFormatProvider provider)
   at System.Convert.ToInt32(Object value)
   at MySql.Data.Types.MySqlInt32.MySql.Data.Types.IMySqlValue.WriteValue(MySqlPacket packet, Boolean binary, Object val, Int32 length)
   at MySql.Data.MySqlClient.MySqlParameter.Serialize(MySqlPacket packet, Boolean binary, MySqlConnectionStringBuilder settings)
   at MySql.Data.MySqlClient.Statement.SerializeParameter(MySqlParameterCollection parameters, MySqlPacket packet, String parmName, Int32 parameterIndex)
   at MySql.Data.MySqlClient.Statement.InternalBindParameters(String sql, MySqlParameterCollection parameters, MySqlPacket packet)
   at MySql.Data.MySqlClient.Statement.BindParameters()
   at MySql.Data.MySqlClient.PreparableStatement.Execute()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
   at ConsoleApplication.Program.Main(String[] args) in Program.cs:line 20

Suggested fix:
Respect the underlying type of Enum parameters and serialize to the appropriate type.
MySql.Data/parameter.cs seems to indicate that all Enum parameters are treated as Int32

case "Object":
          default:
#if RT
            if (t.GetTypeInfo().BaseType == typeof(Enum))
#else
            if( t.BaseType == typeof( Enum ) )
#endif
              MySqlDbType = MySqlDbType.Int32;
            else
              MySqlDbType = MySqlDbType.Blob;
            break;
[30 Jan 2017 7:34] Chiranjeevi Battula
Hello  Tim Wilkens,

Thank you for the bug report and test case.
Verified this behavior on Visual Studio 2013 (C#.Net) and Connector/NET 6.9.9 version.

Thanks,
Chiranjeevi.
[30 Jan 2017 7:35] Chiranjeevi Battula
Screenshot

Attachment: 84701.png (image/png, text), 163.28 KiB.

[24 Nov 2020 16:42] Christine Cole
Posted by developer:
 
Fixed as of the upcoming MySQL Connector/NET 8.0.23 release, and here's the proposed changelog entry from the documentation team:

Without validation, an underlying 64-bit enumeration value passed in as a
MySQL command parameter defaulted to type Int32 and produced an overflow
exception.

Thank you for the bug report.