Description:
I have discovered problem with implementation of MySql.Data.MySqlClient.PreparedStatement.
In method Execute there is MySqlParameterCollection parameters parameter.
this parameter is converted into BitArray and then into byte[]
In case parameters.Count == 0 problem occurs with
nullMap.CopyTo( nullMapBytes, 0 );
nullMap is BitArray of Length = 0
and CopyTo (if implemented properly -> found in MSDN specs and in Mono too)
fails with ArgumentException as index (0) is >= Destination array length.
MS .NET (1.1, 2.0) ignores this, but Mono doesn't and my question about it was answered as: "Should we simulate this bug?"
How to repeat:
This is testing piece of code for that bug. It doesn't use MySql.Data, but it simulates the problem:
using System;
using System.Collections;
namespace BitArrTest
{
        /// <summary>
        /// Summary description for Class1.
        /// </summary>
        class Class1
        {
                /// <summary>
                /// The main entry point for the application.
                /// </summary>
                [STAThread]
                static void Main(string[] args)
                {
                        ArrayList al = new ArrayList();
                        //al.Add(1);
                        //al.Add(0);
                        BitArray ba = new BitArray(al.Count);
                        for(int i = 0; i < al.Count; i++)
                                if((int)al[i] != 0)
                                        ba[i] = true;
                                else
                                        ba[i] = false;
                        byte[] bya = new byte[(al.Count+7)/8];
                        ba.CopyTo(bya, 0);
                        Console.WriteLine("Done");
                }
        }
}
And this is piece of code inside MySql.Data.MySqlClient.PreparedStatement:
		public CommandResult Execute( MySqlParameterCollection parameters )
		{
			if (parameters.Count < paramList.Length)
				throw new MySqlException( "Invalid number of parameters for statement execute" );
			PacketWriter packet = new PacketWriter();
			packet.Driver = (NativeDriver)driver;
			//TODO: support long data here
			// create our null bitmap
			BitArray nullMap = new BitArray( parameters.Count ); //metaData.Length );
			for (int x=0; x < parameters.Count; x++)
			{
				if (parameters[x].Value == DBNull.Value)
					nullMap[x] = true;
			}
			byte[] nullMapBytes = new byte[ (parameters.Count + 7)/8 ];
			nullMap.CopyTo( nullMapBytes, 0 );
As you can see it is almost the same.
Suggested fix:
Well, how to fix it. I suggest following update:
		public CommandResult Execute( MySqlParameterCollection parameters )
		{
			if (parameters.Count < paramList.Length)
				throw new MySqlException( "Invalid number of parameters for statement execute" );
			PacketWriter packet = new PacketWriter();
			packet.Driver = (NativeDriver)driver;
			//TODO: support long data here
			// create our null bitmap
			BitArray nullMap = new BitArray( parameters.Count ); //metaData.Length );
			for (int x=0; x < parameters.Count; x++)
			{
				if (parameters[x].Value == DBNull.Value)
					nullMap[x] = true;
			}
			byte[] nullMapBytes = new byte[ (parameters.Count + 7)/8 ];
			if(nullMapBytes.Length > 0)	// This fix problem with ArgumentException and nullMapBytes is already created and in case of length=0 there is no data to copy...
				nullMap.CopyTo( nullMapBytes, 0 );
Very simple and now it follows .NET specifications and works with Mono.
  
 
 
 
 
 
 
Description: I have discovered problem with implementation of MySql.Data.MySqlClient.PreparedStatement. In method Execute there is MySqlParameterCollection parameters parameter. this parameter is converted into BitArray and then into byte[] In case parameters.Count == 0 problem occurs with nullMap.CopyTo( nullMapBytes, 0 ); nullMap is BitArray of Length = 0 and CopyTo (if implemented properly -> found in MSDN specs and in Mono too) fails with ArgumentException as index (0) is >= Destination array length. MS .NET (1.1, 2.0) ignores this, but Mono doesn't and my question about it was answered as: "Should we simulate this bug?" How to repeat: This is testing piece of code for that bug. It doesn't use MySql.Data, but it simulates the problem: using System; using System.Collections; namespace BitArrTest { /// <summary> /// Summary description for Class1. /// </summary> class Class1 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { ArrayList al = new ArrayList(); //al.Add(1); //al.Add(0); BitArray ba = new BitArray(al.Count); for(int i = 0; i < al.Count; i++) if((int)al[i] != 0) ba[i] = true; else ba[i] = false; byte[] bya = new byte[(al.Count+7)/8]; ba.CopyTo(bya, 0); Console.WriteLine("Done"); } } } And this is piece of code inside MySql.Data.MySqlClient.PreparedStatement: public CommandResult Execute( MySqlParameterCollection parameters ) { if (parameters.Count < paramList.Length) throw new MySqlException( "Invalid number of parameters for statement execute" ); PacketWriter packet = new PacketWriter(); packet.Driver = (NativeDriver)driver; //TODO: support long data here // create our null bitmap BitArray nullMap = new BitArray( parameters.Count ); //metaData.Length ); for (int x=0; x < parameters.Count; x++) { if (parameters[x].Value == DBNull.Value) nullMap[x] = true; } byte[] nullMapBytes = new byte[ (parameters.Count + 7)/8 ]; nullMap.CopyTo( nullMapBytes, 0 ); As you can see it is almost the same. Suggested fix: Well, how to fix it. I suggest following update: public CommandResult Execute( MySqlParameterCollection parameters ) { if (parameters.Count < paramList.Length) throw new MySqlException( "Invalid number of parameters for statement execute" ); PacketWriter packet = new PacketWriter(); packet.Driver = (NativeDriver)driver; //TODO: support long data here // create our null bitmap BitArray nullMap = new BitArray( parameters.Count ); //metaData.Length ); for (int x=0; x < parameters.Count; x++) { if (parameters[x].Value == DBNull.Value) nullMap[x] = true; } byte[] nullMapBytes = new byte[ (parameters.Count + 7)/8 ]; if(nullMapBytes.Length > 0) // This fix problem with ArgumentException and nullMapBytes is already created and in case of length=0 there is no data to copy... nullMap.CopyTo( nullMapBytes, 0 ); Very simple and now it follows .NET specifications and works with Mono.