mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Bug#45010: invalid memory reads during parsing some strange statements
The problem is that the lexer could inadvertently skip over the end of a query being parsed if it encountered a malformed multibyte character. A specially crated query string could cause the lexer to jump up to six bytes past the end of the query buffer. Another problem was that the laxer could use unfiltered user input as a signed array index for the parser maps (having upper and lower bounds 0 and 256 respectively). The solution is to ensure that the lexer only skips over well-formed multibyte characters and that the index value of the parser maps is always a unsigned value.
This commit is contained in:
parent
1c07007f06
commit
69fbbdc19d
3 changed files with 43 additions and 8 deletions
|
@ -165,7 +165,7 @@ CREATE TABLE `good
|
|||
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');
|
||||
|
|
|
@ -32,10 +32,10 @@ sys_var_long_ptr trg_new_row_fake_var(0, 0);
|
|||
|
||||
/* Macros to look like lex */
|
||||
|
||||
#define yyGet() *(lip->ptr++)
|
||||
#define yyGetLast() lip->ptr[-1]
|
||||
#define yyPeek() lip->ptr[0]
|
||||
#define yyPeek2() lip->ptr[1]
|
||||
#define yyGet() ((uchar)*(lip->ptr++))
|
||||
#define yyGetLast() ((uchar)lip->ptr[-1])
|
||||
#define yyPeek() ((uchar)lip->ptr[0])
|
||||
#define yyPeek2() ((uchar)lip->ptr[1])
|
||||
#define yyUnget() lip->ptr--
|
||||
#define yySkip() lip->ptr++
|
||||
#define yyLength() ((uint) (lip->ptr - lip->tok_start)-1)
|
||||
|
@ -813,9 +813,11 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
}
|
||||
}
|
||||
#ifdef USE_MB
|
||||
else if (var_length < 1)
|
||||
break; // Error
|
||||
lip->ptr+= var_length-1;
|
||||
else if (use_mb(cs))
|
||||
{
|
||||
if ((var_length= my_ismbchar(cs, lip->ptr-1, lip->end_of_query)))
|
||||
lip->ptr+= var_length-1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (double_quotes)
|
||||
|
|
|
@ -16647,6 +16647,38 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Read and parse arguments and MySQL options from my.cnf
|
||||
*/
|
||||
|
@ -16949,6 +16981,7 @@ static struct my_tests_st my_tests[]= {
|
|||
#endif
|
||||
{ "test_bug41078", test_bug41078 },
|
||||
{ "test_bug20023", test_bug20023 },
|
||||
{ "test_bug45010", test_bug45010 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue