Bug #14060 Exception when using varchar parameters with shorter length than specified
Submitted: 16 Oct 2005 20:34 Modified: 15 Jun 2007 9:15
Reporter: Bart King Email Updates:
Status: No Feedback Impact on me:
None 
Category:Connector / NET Severity:S3 (Non-critical)
Version:1.0.6 OS:Windows (Windows XP SP2)
Assigned to: CPU Architecture:Any

[16 Oct 2005 20:34] Bart King
Description:
It seems when using a MySqlParameter declared as below, causes an exception.

  MySqlParameter parm = new MySqlParameter();
  parm.MySqlDataType = MySqlDbType.VarChar;
  parm.Size = 128; // <-- note!
  parm.Value = "Hello there"; // shorter than 128 characters!

How to repeat:
When you try an execute a query (such as "insert into table (foo) values (?foo)") and attach the specified parameter to the MySqlCommand, an exception is thrown saying "Index and length must refer to a location within the string. Parameter name: length".

Suggested fix:
I fixed the problem by changing MySqlClient\Types\MySqlString.cs to add a sanity check to the length. This is from line 52 from the 1.0.6 release:

internal override void Serialize(PacketWriter writer, bool binary, object value, int length)
{
	string v = value.ToString();
	if (length > 0) /* bart was here */
	{
		if(length > v.Length) // added sanity check here
			length = v.Length;
		v = v.Substring(0, length);
	}

	if (binary)
		writer.WriteLenString( v );
	else
		writer.WriteStringNoNull( "'" + EscapeString(v) + "'" );
}
[18 Oct 2005 8:12] Vasily Kishkin
Sorry...I was not able to reproduce the bug on my test case. Could you please provide full text of your test case ? Thanks
[19 Nov 2005 0:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[21 Sep 2006 19:34] Chris Nucci
Upon setting the Value of a MySqlParameter for Byte[] or String types, the Size value is reset to the length of the given Value.  This is contradictory to the System.Data.SqlClient, System.Data.OleDb, and System.Data.OdbcClient implementations, as well as the ByteFX implementation of the MySqlClient, where the Size not automatically changed.

If this feature is removed then a related bug will be MySqlString.Serialize() function.  The parameter size is passed down to Serialize() as length and used by a Substring() call. If the value is less than the length, the Substring() function will throw an ArgumentOutOfRangeException.

Suggested fix:
Do not update the Size of the MySqlParameter when a Value is set, then only call the Substring() in MySqlString.Serialize() if the value length is greater than the length parameter.

Example:
Dim p1 As New MySql.Data.MySqlClient.MySqlParameter
With p1
    .Size = 10
    .Value = "12345"
End With

'The Size of p1 should now be 5
'In the following, the Size will remain 10

Dim p2 As New System.Data.SqlClient.SqlParameter
With p2
    .Size = 10
    .Value = "12345"
End With

Dim p3 As New System.Data.OleDb.OleDbParameter
With p3
    .Size = 10
    .Value = "12345"
End With

Dim p4 As New System.Data.Odbc.OdbcParameter
With p4
    .Size = 10
    .Value = "12345"
End With

Dim p5 As New ByteFX.Data.MySqlClient.MySqlParameter
With p5
    .Size = 10
    .Value = "12345"
End With
[15 May 2007 9:15] Tonci Grgin
I have lost this out of sight... Chris, Bart, is this still a problem with new version?
[15 Jun 2007 23:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[18 Jan 2008 23:53] Chris Nucci
Yes, this is still a problem as of 5.0.8.1.