diff options
author | gshchepa/uchum@gleb.loc <> | 2007-07-30 04:35:16 +0500 |
---|---|---|
committer | gshchepa/uchum@gleb.loc <> | 2007-07-30 04:35:16 +0500 |
commit | 1eb20fc0a547e17df78f2d086b61431f63b824d5 (patch) | |
tree | 217ada9fdf9cbaee6091b563f7c98f522334fb25 /sql | |
parent | e53a484ec9ccc1543651a3c892e61d1773997ca3 (diff) | |
download | mariadb-git-1eb20fc0a547e17df78f2d086b61431f63b824d5.tar.gz |
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.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item.h | 11 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 3 |
4 files changed, 15 insertions, 5 deletions
diff --git a/sql/item.cc b/sql/item.cc index bd47fb706a6..9612fbc5243 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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; diff --git a/sql/item.h b/sql/item.h index 72236cb5e63..23f6977a0f8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -960,9 +960,18 @@ public: 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 */ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fd8724b2171..8f4d407a5b0 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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('")); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6fbd521e302..b0e59d0f8dc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7708,7 +7708,8 @@ simple_ident: Item_splocal *splocal; splocal= new Item_splocal($1, spv->offset, spv->type, lip->tok_start_prev - - lex->sphead->m_tmp_query); + lex->sphead->m_tmp_query, + lip->tok_end - lip->tok_start_prev); #ifndef DBUG_OFF if (splocal) splocal->m_sp= lex->sphead; |