summaryrefslogtreecommitdiff
path: root/sql/item_func.h
diff options
context:
space:
mode:
authorPraveenkumar Hulakund <praveenkumar.hulakund@oracle.com>2012-11-07 19:08:33 +0530
committerPraveenkumar Hulakund <praveenkumar.hulakund@oracle.com>2012-11-07 19:08:33 +0530
commitd912a758b02399c28cb30d97496ad5cdab35d214 (patch)
tree81c1dddbb0ffde40a0473341f3c2a1f8b07d62ac /sql/item_func.h
parentf5fbcfe3c8b87f0a66293a9d69e65ed2a127180c (diff)
downloadmariadb-git-d912a758b02399c28cb30d97496ad5cdab35d214.tar.gz
Bug#14466617 - INVALID WRITES AND/OR CRASH WITH USER
VARIABLES Analysis: ------------- After executing the query, new value of the user defined variables are set in the function "select_dumpvar::send_data". "select_dumpvar::send_data" first calls function "Item_func_set_user_var::save_item_result()". This function checks the nullness of the Item_field passed as parameter to it and saves it. The nullness of item is stored with arg[0]'s null_value flag. Then "select_dumpvar::send_data" calls "Item_func_set_user_var::update()" which notices null result that was saved and calls "Item_func_set_user_var:: update_hash". But here null_value is not set and args[0] is different from that given to function "Item_func_set_user_var:: set_item_result()". This causes "Item_func_set_user_var:: update_hash" function to believe that its getting non-null value. "user_var_entry::length" set to 0 and hence "user_var_entry::value" is made to point to extra_area allocated in "user_var_entry". And "Item_func_set_user_var::update_hash" tries to write at memory beyond extra_area for result type DECIMAL. Because of this invalid write issue is reported by Valgrind. Before this bug was introduced, we avoided this problem by creating "Item_func_set_user_var" object with the same Item_field as arg[0] and as parameter to Item_func_set_user_var::save_item_result(). But now they are refering to different args[0]. Because of this null_value flag set in parameter Item_field in function "Item_func_set_user_var::save_item_result()" is not reflected in "Item_func_set_user_var" object. Fix: ------------ This issue is reported on versions 5.5.24. Issue does not exists in 5.5.23, 5.1, 5.6 and trunk. This issue was introduced by revid:georgi.kodinov@oracle.com-20120309130449-82e3bs5v3et1x0ef (fix for bug #12408412), which was pushed into 5.5 and later releases. This patch has later been reversed in 5.6 and trunk by revid:norvald.ryeng@oracle.com-20121010135242-xj34gg73h04hrmyh (fix for bug #14664077). Backported this patch in 5.5 also to fix this issue. sql/item_func.cc: here unsigned value is converted to signed value. sql/item_func.h: last_insert_id() gives an auto_incremented value which can be positive only,so defined it as a unsigned longlong sets the unsigned_flag to 1.
Diffstat (limited to 'sql/item_func.h')
-rw-r--r--sql/item_func.h18
1 files changed, 16 insertions, 2 deletions
diff --git a/sql/item_func.h b/sql/item_func.h
index 6ac0b1b82bd..b897dcfaaaa 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1457,6 +1457,20 @@ class Item_func_set_user_var :public Item_func
user variable it the first connection context).
*/
my_thread_id entry_thread_id;
+ /**
+ Delayed setting of non-constness.
+
+ Normally, Item_func_get_user_var objects are tagged as not const
+ when Item_func_set_user_var::fix_fields() is called for the same
+ variable in the same query. If delayed_non_constness is set, the
+ tagging is delayed until the variable is actually set. This means
+ that Item_func_get_user_var objects will still be treated as a
+ constant by the optimizer and executor until the variable is
+ actually changed.
+
+ @see select_dumpvar::send_data().
+ */
+ bool delayed_non_constness;
char buffer[MAX_FIELD_WIDTH];
String value;
my_decimal decimal_buff;
@@ -1471,9 +1485,9 @@ class Item_func_set_user_var :public Item_func
public:
LEX_STRING name; // keep it public
- Item_func_set_user_var(LEX_STRING a,Item *b)
+ Item_func_set_user_var(LEX_STRING a,Item *b, bool delayed)
:Item_func(b), cached_result_type(INT_RESULT),
- entry(NULL), entry_thread_id(0), name(a)
+ entry(NULL), entry_thread_id(0), delayed_non_constness(delayed), name(a)
{}
enum Functype functype() const { return SUSERVAR_FUNC; }
double val_real();