summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorgshchepa/uchum@gleb.loc <>2007-07-30 04:35:16 +0500
committergshchepa/uchum@gleb.loc <>2007-07-30 04:35:16 +0500
commit1eb20fc0a547e17df78f2d086b61431f63b824d5 (patch)
tree217ada9fdf9cbaee6091b563f7c98f522334fb25 /sql
parente53a484ec9ccc1543651a3c892e61d1773997ca3 (diff)
downloadmariadb-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.cc4
-rw-r--r--sql/item.h11
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_yacc.yy3
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;