Bug #44960 backslash in string - connector return exeption

Submitted: 19 May 2009 18:46 Modified: 26 May 2009 13:18
Reporter: Moshe Lampert Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S3 (Non-critical)
Version:6.0.3 OS:Any
Assigned to: Vladislav Vaintroub CPU Architecture:Any
Tags: regression

[19 May 2009 18:46] Moshe Lampert
Description:
SQL string with escaped backslash inside.

examples:

insert into pb_im set m_from=1, m_to=1, m_content='\\=';
insert into pb_im set m_from=1, m_to=1, m_content='\\'; /* works sometimes, fail somtimes */

works on Query Browser/CLI/connector 5.x, fail on 6.0.3:

Index and length must refer to a location within the string. 
Parameter name: length 
at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy) 
at MySql.Data.MySqlClient.MySqlTokenizer.NextParameter() 
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 be‎havior) 
at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() / Scalar / etc

How to repeat:
open connection, end execute SQL with "=\" escaped and sometimes text and "\" (escaped = "\\") in the end of the string

insert into pb_im set m_from=1, m_to=1, m_content='\\=';
insert into pb_im set m_from=1, m_to=1, m_content='ב6\\';
insert into pb_im set m_from=1, m_to=1, m_content='ב..\\';
[20 May 2009 8:04] Tonci Grgin
Hi Moshe and thanks for your report.

I would like to see compact but complete test case attached as well as MySQL server info and my.ini file.
[20 May 2009 8:36] Tonci Grgin
Bug#44973 was marked as duplicate of this report.
[20 May 2009 8:43] Moshe Lampert
MySQL Version: 5.1.30-2 (@debian)
Connector Version: 6.0.3
MySQL Encoding: utf-8

Using Conn As New MySqlConnection(...)
	Conn.Open()
	Dim Cmd As new MySQLCommand("",Conn)
	Cmd.CommandText="insert into pb_im set m_from=1, m_to=1, m_content='\\=';"
	Cmd.ExecuteNonQuery()

End Using ' and close/dispose the connection
[20 May 2009 8:47] Tonci Grgin
Moshe, please please attach *full* test case. Not only am I missing DDL/DML statements but also a connection string...
[20 May 2009 10:44] Moshe Lampert
connstring:
server=*;user id=*; password=*; database=*; pooling=true; Min Pool Size=40;Max Pool Size=150; Connect Timeout=5;default command timeout=10

There is no other code, as my testcase is simple SQL queries (in this code - some small ASHX code).
[20 May 2009 12:17] Tonci Grgin
Ok, this test case:
      MySqlConnection con = new MySqlConnection();
      con.ConnectionString = "DataSource=**;Database=test;UserID=**;Password=**;PORT=**;logging=True;";
      con.Open();
      MySqlCommand cmdCreateTable = new MySqlCommand("DROP TABLE IF EXISTS bug44973", con);
      cmdCreateTable.ExecuteNonQuery();
      cmdCreateTable.CommandText = "CREATE TABLE `bug44973`(`ID` int UNSIGNED NOT NULL auto_increment, `file_name` varchar(256) COLLATE latin1_bin NOT NULL, PRIMARY KEY (`ID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;";
      cmdCreateTable.ExecuteNonQuery();

      string query = "INSERT INTO bug44973 VALUES (NULL, '2bsl=\\-1bsl=\')";
      cmdCreateTable.CommandText = query;
      Assert.AreEqual(1, cmdCreateTable.ExecuteNonQuery());
      cmdCreateTable.Dispose();
      con.Close();
      con.Dispose();

produces following output:
[20.5.2009 14:10:45] - Executing command QUERY with text ='SHOW VARIABLES'
[20.5.2009 14:10:45] - Executing command QUERY with text ='SHOW COLLATION'
[20.5.2009 14:10:45] - Executing command QUERY with text ='SET NAMES utf8;SET character_set_results=NULL'
[20.5.2009 14:10:46] - Executing command QUERY with text ='DROP TABLE IF EXISTS bug44973'
[20.5.2009 14:10:46] - Executing command QUERY with text ='CREATE TABLE `bug44973`(`ID` int UNSIGNED NOT NULL auto_increment, `file_name` varchar(256) COLLATE latin1_bin NOT NULL, PRIMARY KEY (`ID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin'
[20.5.2009 14:10:46] - Executing command QUERY with text ='INSERT INTO bug44973 VALUES (NULL, '2bsl=\-1bsl=')' <<<<

So, I did not get any crashes but what I see appears as regression from Bug#4505 to me. Adding reference to Bug#44973 too.
[20 May 2009 12:55] Alexander Sosedkin
Look for the string that you want to insert '2bsl=\\-1bsl=\'
and a string in the output '2bsl=\-1bsl=', I think you can see the difference?

Or change in the your test сase, for insert a string '\\', which should
insert a backslash, you get an exception:
System.ArgumentOutOfRangeException: Index and length must refer to a location within the
string. Parameter name: length
[20 May 2009 13:05] Tonci Grgin
Alexander, of course I see :) And as for later part (inserting '\\') I made reference to your bug.
[20 May 2009 13:11] Alexander Sosedkin
OK :)
Thank you!
[21 May 2009 8:05] Alexander Sosedkin
I rushed to the conclusion, then that variable is "escaped" is not needed.
In my opinion code "MySqlTokenizer.ReadQuotedToken" should look like:

private void ReadQuotedToken(char quoteChar)
{
    startIndex = pos-1;
    bool escaped = false;

    while (pos < sql.Length)
    {
        char c = sql[pos];

        if (escaped)
            escaped = false;
        else if (c == quoteChar)
            break;
        else if (c == '\\' && BackslashEscapes)
            escaped = true;
            
        pos++;
    }
    
    pos++;
    Quoted = true;
    stopIndex = pos;
}

If this can help you.
[21 May 2009 8:13] Tonci Grgin
Alexander, thanks for your contribution.
[22 May 2009 21:45] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/74815
[22 May 2009 21:46] Reggie Burnett
fixed in 6.0.4
[26 May 2009 13:18] Tony Bedford
An entry was added to the 6.0.4 changelog:

A SQL query string containing an escaped backslash caused an exception to be generated:

Index and length must refer to a location within the string. 
Parameter name: length 
at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean
fAlwaysCopy) 
at MySql.Data.MySqlClient.MySqlTokenizer.NextParameter() 
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 be‎havior) 
at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
[5 Aug 2009 4:29] Dennis Haney
It seems the actual bug wasnt really fixed...

public string NextParameter()
    {
        while (this.FindToken())
        {
            if ((this.stopIndex - this.startIndex) >= 2)
            {
                this.sql.Substring(this.startIndex, this.stopIndex - this.startIndex).Trim();                  <----- what on earth does this line do :D
                char ch = this.sql[this.startIndex];
                char ch2 = this.sql[this.startIndex + 1];
                if ((ch == '?') || ((ch == '@') && (ch2 != '@')))
                {
                    return this.sql.Substring(this.startIndex, this.stopIndex - this.startIndex);
                }
            }
        }
        return null;
    }

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.048 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.