diff options
author | Praveenkumar Hulakund <praveenkumar.hulakund@oracle.com> | 2012-11-07 19:08:33 +0530 |
---|---|---|
committer | Praveenkumar Hulakund <praveenkumar.hulakund@oracle.com> | 2012-11-07 19:08:33 +0530 |
commit | d912a758b02399c28cb30d97496ad5cdab35d214 (patch) | |
tree | 81c1dddbb0ffde40a0473341f3c2a1f8b07d62ac /sql/item_func.h | |
parent | f5fbcfe3c8b87f0a66293a9d69e65ed2a127180c (diff) | |
download | mariadb-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.h | 18 |
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(); |