Commit 1eb20fc0 authored by gshchepa/uchum@gleb.loc's avatar gshchepa/uchum@gleb.loc
Browse files

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
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -6303,4 +6303,15 @@ DROP VIEW v1;
DROP FUNCTION f1;
DROP FUNCTION f2;
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
+21 −0
Original line number Diff line number Diff line
@@ -7278,4 +7278,25 @@ DROP FUNCTION f1;
DROP FUNCTION f2;
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
+2 −2
Original line number Diff line number Diff line
@@ -1053,9 +1053,9 @@ bool Item_sp_variable::is_null()
Item_splocal::Item_splocal(const LEX_STRING &sp_var_name,
                           uint sp_var_idx,
                           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),
   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;

+10 −1
Original line number Diff line number Diff line
@@ -960,9 +960,18 @@ class Item_splocal :public Item_sp_variable,
    SP variable in query text.
  */
  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,
               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 */

+1 −1
Original line number Diff line number Diff line
@@ -864,7 +864,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
    
    /* append the text between sp ref occurences */
    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 */
    res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('"));
Loading