Commit d4967659 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds

Lex_input_stream::scan_ident_delimited() could go beyond the end
of the input when a starting backtick (`) delimiter did not have a
corresponding ending backtick.

Fix: catch the case when yyGet() returns 0, which means
either eof-of-query or straight 0x00 byte inside backticks,
and make the parser fail on syntax error, displaying the left
backtick as the syntax error place.

In case of filename in a script like this:

SET CHARACTER_SET_CLIENT=17; -- 17 is 'filename'
SELECT doc.`Children`.0 FROM t1;

the ending backtick was not recognized as such because my_charlen() returns 0 for
a straight backtick (backticks must normally be encoded as @0060 in filename).

The same fix works for 'filename': the execution skips the backtick
and reaches the end of the query, then yyGet() returns 0.
This fix is OK for now. But eventually 'filename' should either be disallowed
as a parser character set, or fixed to handle encoded punctuation properly.
parent b3e9798f
...@@ -21,3 +21,10 @@ SET NAMES utf8; ...@@ -21,3 +21,10 @@ SET NAMES utf8;
SELECT @a:=CONVERT('aя' USING filename) AS `@a`, BINARY @a, REVERSE(@a), HEX(@a), HEX(REVERSE(@a)); SELECT @a:=CONVERT('aя' USING filename) AS `@a`, BINARY @a, REVERSE(@a), HEX(@a), HEX(REVERSE(@a));
@a BINARY @a REVERSE(@a) HEX(@a) HEX(REVERSE(@a)) @a BINARY @a REVERSE(@a) HEX(@a) HEX(REVERSE(@a))
aя a@r1 яa 61407231 40723161 aя a@r1 яa 61407231 40723161
#
# MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds
#
SET CHARACTER_SET_CLIENT=17;
SELECT doc.`Children`.0 FROM t1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?Children??0?FROM?t1' at line 1
SET NAMES latin1;
...@@ -27,3 +27,13 @@ select convert(convert(',' using filename) using binary); ...@@ -27,3 +27,13 @@ select convert(convert(',' using filename) using binary);
--echo # --echo #
SET NAMES utf8; SET NAMES utf8;
SELECT @a:=CONVERT('aя' USING filename) AS `@a`, BINARY @a, REVERSE(@a), HEX(@a), HEX(REVERSE(@a)); SELECT @a:=CONVERT('aя' USING filename) AS `@a`, BINARY @a, REVERSE(@a), HEX(@a), HEX(REVERSE(@a));
--echo #
--echo # MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds
--echo #
SET CHARACTER_SET_CLIENT=17;
--error ER_PARSE_ERROR
SELECT doc.`Children`.0 FROM t1;
SET NAMES latin1;
...@@ -1760,4 +1760,11 @@ SELECT @@GLOBAL.password; ...@@ -1760,4 +1760,11 @@ SELECT @@GLOBAL.password;
ERROR HY000: Unknown system variable 'password' ERROR HY000: Unknown system variable 'password'
SELECT @@GLOBAL.role; SELECT @@GLOBAL.role;
ERROR HY000: Unknown system variable 'role' ERROR HY000: Unknown system variable 'role'
#
# MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds
#
EXECUTE IMMEDIATE 'if(`systeminfo /FO LIST';
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`systeminfo /FO LIST' at line 1
EXECUTE IMMEDIATE 'if(`systeminfo';
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`systeminfo' at line 1
End of 10.3 tests End of 10.3 tests
...@@ -1538,4 +1538,13 @@ SELECT @@GLOBAL.password; ...@@ -1538,4 +1538,13 @@ SELECT @@GLOBAL.password;
--error ER_UNKNOWN_SYSTEM_VARIABLE --error ER_UNKNOWN_SYSTEM_VARIABLE
SELECT @@GLOBAL.role; SELECT @@GLOBAL.role;
--echo #
--echo # MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds
--echo #
--error ER_PARSE_ERROR
EXECUTE IMMEDIATE 'if(`systeminfo /FO LIST';
--error ER_PARSE_ERROR
EXECUTE IMMEDIATE 'if(`systeminfo';
--echo End of 10.3 tests --echo End of 10.3 tests
...@@ -2206,8 +2206,17 @@ int Lex_input_stream::scan_ident_delimited(THD *thd, ...@@ -2206,8 +2206,17 @@ int Lex_input_stream::scan_ident_delimited(THD *thd,
uchar c, quote_char= m_tok_start[0]; uchar c, quote_char= m_tok_start[0];
DBUG_ASSERT(m_ptr == m_tok_start + 1); DBUG_ASSERT(m_ptr == m_tok_start + 1);
while ((c= yyGet())) for ( ; ; )
{ {
if (!(c= yyGet()))
{
/*
End-of-query or straight 0x00 inside a delimited identifier.
Return the quote character, to have the parser fail on syntax error.
*/
m_ptr= (char *) m_tok_start + 1;
return quote_char;
}
int var_length= my_charlen(cs, get_ptr() - 1, get_end_of_query()); int var_length= my_charlen(cs, get_ptr() - 1, get_end_of_query());
if (var_length == 1) if (var_length == 1)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment