From 7bbdb8408bc36d6c9a8251c9a133add1c395e5c5 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Fri, 18 Jun 2004 04:16:08 +0400 Subject: [PATCH] Fix for bug#4105 "Server crash on attempt to prepare a statement with character set introducer": add new item type to be returned before from Item_param until it's value is set. This way items like Item_bool_func2 and udf_handler won't treat this item as constant literal when statement is prepared. --- mysql-test/r/ps.result | 6 ++++++ mysql-test/t/ps.test | 9 ++++++++- sql/item.cc | 12 +++++++++++- sql/item.h | 3 ++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index fd3a7d54b4d..e03952efe13 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -113,3 +113,9 @@ execute stmt1 using @ivar; ? 1234 drop table t1,t2; +PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?"; +set @var='A'; +EXECUTE stmt1 USING @var; +_utf8 'A' collate utf8_bin = ? +1 +DEALLOCATE PREPARE stmt1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d9e0f0852c5..f379fb3eebe 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -116,4 +116,11 @@ prepare stmt1 from @str2; execute stmt1 using @ivar; drop table t1,t2; - +# +# Bug #4105: Server crash on attempt to prepare a statement with character +# set introducer +# +PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?"; +set @var='A'; +EXECUTE stmt1 USING @var; +DEALLOCATE PREPARE stmt1; diff --git a/sql/item.cc b/sql/item.cc index 853f5bc8ecc..39586551e12 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -628,7 +628,8 @@ default_set_param_func(Item_param *param, Item_param::Item_param(unsigned pos_in_query_arg) : state(NO_VALUE), item_result_type(STRING_RESULT), - item_type(STRING_ITEM), + /* Don't pretend to be a literal unless value for this item is set. */ + item_type(PARAM_ITEM), param_type(MYSQL_TYPE_STRING), pos_in_query(pos_in_query_arg), set_param_func(default_set_param_func) @@ -827,6 +828,15 @@ void Item_param::reset() state= NO_VALUE; maybe_null= 1; null_value= 0; + /* + Don't reset item_type to PARAM_ITEM: it's only needed to guard + us from item optimizations at prepare stage, when item doesn't yet + contain a literal of some kind. + In all other cases when this object is accessed its value is + set (this assumption is guarded by 'state' and + DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_* + methods). + */ } diff --git a/sql/item.h b/sql/item.h index 3cb1d6e2aa4..52a44a65526 100644 --- a/sql/item.h +++ b/sql/item.h @@ -98,7 +98,8 @@ public: COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, - SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER}; + SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, + PARAM_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };