diff options
-rw-r--r-- | mysql-test/r/ctype_recoding.result | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 9 | ||||
-rw-r--r-- | sql/sql_lex.h | 8 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 29 |
4 files changed, 40 insertions, 8 deletions
diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 304e37facb1..ee95812c03e 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -165,7 +165,7 @@ CREATE TABLE `goodÐÌÏÈÏ` (a int); ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ' SET NAMES utf8; CREATE TABLE `goodÐÌÏÈÏ` (a int); -ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ` (a int)' +ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ' set names latin1; create table t1 (a char(10) character set koi8r, b text character set koi8r); insert into t1 values ('test','test'); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 444a8ae0736..2adbc44eb12 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1105,9 +1105,12 @@ int MYSQLlex(void *arg, void *yythd) } } #ifdef USE_MB - else if (var_length < 1) - break; // Error - lip->skip_binary(var_length-1); + else if (use_mb(cs)) + { + if ((var_length= my_ismbchar(cs, lip->get_ptr() - 1, + lip->get_end_of_query()))) + lip->skip_binary(var_length-1); + } #endif } if (double_quotes) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 22b7d2e359c..76fd5354c51 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1190,7 +1190,7 @@ public: Get a character, and advance in the stream. @return the next character to parse. */ - char yyGet() + unsigned char yyGet() { char c= *m_ptr++; if (m_echo) @@ -1202,7 +1202,7 @@ public: Get the last character accepted. @return the last character accepted. */ - char yyGetLast() + unsigned char yyGetLast() { return m_ptr[-1]; } @@ -1210,7 +1210,7 @@ public: /** Look at the next character to parse, but do not accept it. */ - char yyPeek() + unsigned char yyPeek() { return m_ptr[0]; } @@ -1219,7 +1219,7 @@ public: Look ahead at some character to parse. @param n offset of the character to look up */ - char yyPeekn(int n) + unsigned char yyPeekn(int n) { return m_ptr[n]; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 75789c1beb2..9d61d6edd3e 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -17947,6 +17947,34 @@ static void test_bug41078(void) DBUG_VOID_RETURN; } +/** + Bug#45010: invalid memory reads during parsing some strange statements +*/ +static void test_bug45010() +{ + int rc; + const char query1[]= "select a.\x80", + query2[]= "describe `table\xef"; + + DBUG_ENTER("test_bug45010"); + myheader("test_bug45010"); + + rc= mysql_query(mysql, "set names utf8"); + myquery(rc); + + /* \x80 (-128) could be used as a index of ident_map. */ + rc= mysql_real_query(mysql, query1, sizeof(query1) - 1); + DIE_UNLESS(rc); + + /* \xef (-17) could be used to skip 3 bytes past the buffer end. */ + rc= mysql_real_query(mysql, query2, sizeof(query2) - 1); + DIE_UNLESS(rc); + + rc= mysql_query(mysql, "set names default"); + myquery(rc); + + DBUG_VOID_RETURN; +} /** Bug#44495: Prepared Statement: @@ -18301,6 +18329,7 @@ static struct my_tests_st my_tests[]= { { "test_change_user", test_change_user }, { "test_bug30472", test_bug30472 }, { "test_bug20023", test_bug20023 }, + { "test_bug45010", test_bug45010 }, { "test_bug31418", test_bug31418 }, { "test_bug31669", test_bug31669 }, { "test_bug28386", test_bug28386 }, |