Fixed bug #30120.

SP with local variables with non-ASCII names crashed the server.

The server replaces SP local variable names with NAME_CONST calls
when putting statements into the binary log. It used UTF8-encoded
item names as variable names for the replacement inside NAME_CONST
calls. However, statement string may be encoded by any
known character set by the SET NAMES statement.
The server used byte length of UTF8-encoded names to increment
the position in the query string that led to array index overrun.
parent e53a484e
...@@ -6303,4 +6303,15 @@ DROP VIEW v1; ...@@ -6303,4 +6303,15 @@ DROP VIEW v1;
DROP FUNCTION f1; DROP FUNCTION f1;
DROP FUNCTION f2; DROP FUNCTION f2;
DROP TABLE t1; DROP TABLE t1;
SET NAMES latin1;
CREATE PROCEDURE p1()
BEGIN
DECLARE INT;
SELECT ;
END|
CALL p1();
NULL
SET NAMES default;
DROP PROCEDURE p1;
End of 5.0 tests End of 5.0 tests
...@@ -7278,4 +7278,25 @@ DROP FUNCTION f1; ...@@ -7278,4 +7278,25 @@ DROP FUNCTION f1;
DROP FUNCTION f2; DROP FUNCTION f2;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #30120 SP with local variables with non-ASCII names crashes server.
#
SET NAMES latin1;
DELIMITER |;
CREATE PROCEDURE p1()
BEGIN
DECLARE INT;
SELECT ;
END|
DELIMITER ;|
CALL p1();
SET NAMES default;
DROP PROCEDURE p1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -1053,9 +1053,9 @@ bool Item_sp_variable::is_null() ...@@ -1053,9 +1053,9 @@ bool Item_sp_variable::is_null()
Item_splocal::Item_splocal(const LEX_STRING &sp_var_name, Item_splocal::Item_splocal(const LEX_STRING &sp_var_name,
uint sp_var_idx, uint sp_var_idx,
enum_field_types sp_var_type, enum_field_types sp_var_type,
uint pos_in_q) uint pos_in_q, uint len_in_q)
:Item_sp_variable(sp_var_name.str, sp_var_name.length), :Item_sp_variable(sp_var_name.str, sp_var_name.length),
m_var_idx(sp_var_idx), pos_in_query(pos_in_q) m_var_idx(sp_var_idx), pos_in_query(pos_in_q), len_in_query(len_in_q)
{ {
maybe_null= TRUE; maybe_null= TRUE;
......
...@@ -960,9 +960,18 @@ class Item_splocal :public Item_sp_variable, ...@@ -960,9 +960,18 @@ class Item_splocal :public Item_sp_variable,
SP variable in query text. SP variable in query text.
*/ */
uint pos_in_query; uint pos_in_query;
/*
Byte length of SP variable name in the statement (see pos_in_query).
The value of this field may differ from the name_length value because
name_length contains byte length of UTF8-encoded item name, but
the query string (see sp_instr_stmt::m_query) is currently stored with
a charset from the SET NAMES statement.
*/
uint len_in_query;
Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx, Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx,
enum_field_types sp_var_type, uint pos_in_q= 0); enum_field_types sp_var_type,
uint pos_in_q= 0, uint len_in_q= 0);
bool is_splocal() { return 1; } /* Needed for error checking */ bool is_splocal() { return 1; } /* Needed for error checking */
......
...@@ -864,7 +864,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) ...@@ -864,7 +864,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
/* append the text between sp ref occurences */ /* append the text between sp ref occurences */
res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos);
prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length; prev_pos= (*splocal)->pos_in_query + (*splocal)->len_in_query;
/* append the spvar substitute */ /* append the spvar substitute */
res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('")); res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('"));
......
...@@ -7708,7 +7708,8 @@ simple_ident: ...@@ -7708,7 +7708,8 @@ simple_ident:
Item_splocal *splocal; Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, spv->type, splocal= new Item_splocal($1, spv->offset, spv->type,
lip->tok_start_prev - lip->tok_start_prev -
lex->sphead->m_tmp_query); lex->sphead->m_tmp_query,
lip->tok_end - lip->tok_start_prev);
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (splocal) if (splocal)
splocal->m_sp= lex->sphead; splocal->m_sp= lex->sphead;
......
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