summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/ctype_recoding.result2
-rw-r--r--sql/sql_lex.cc9
-rw-r--r--sql/sql_lex.h8
-rw-r--r--tests/mysql_client_test.c29
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 },