Bug #84701 Overflow Exception - 64 bit enum value as parameter cast to Int32
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;
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.052 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
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;