diff options
author | Gleb Shchepa <gshchepa@mysql.com> | 2009-05-18 09:21:25 +0500 |
---|---|---|
committer | Gleb Shchepa <gshchepa@mysql.com> | 2009-05-18 09:21:25 +0500 |
commit | 405bd2af117384e009c3feffe1fd7d9019bf9d2b (patch) | |
tree | 0cc46a52d78c3e50ef405932673b7269b7af6590 /sql | |
parent | baeac8762396a181440368c9413d617f0f49aacc (diff) | |
download | mariadb-git-405bd2af117384e009c3feffe1fd7d9019bf9d2b.tar.gz |
Bug #44768: SIGFPE crash when selecting rand from a view containing null
The RAND(N) function where the N is a field of "constant" table
(table of single row) failed with a SIGFPE.
Evaluation of RAND(N) rely on constant status of its argument.
Current server "seeded" random value for each constant argument
only once, in the Item_func_rand::fix_fields method.
Then the server skipped a call to seed_random() in the
Item_func_rand::val_real method for such constant arguments.
However, non-constant state of an argument may be changed
after the call to fix_fields, if an argument is a field of
"constant" table. Thus, pre-initialization of random value
in the fix_fields method is too early.
Initialization of random value by seed_random() has been
removed from Item_func_rand::fix_fields method.
The Item_func_rand::val_real method has been modified to
call seed_random() on the first evaluation of this method
if an argument is a function.
mysql-test/r/func_math.result:
Added test case for bug #44768.
mysql-test/t/func_math.test:
Added test case for bug #44768.
sql/item_func.cc:
Bug #44768: SIGFPE crash when selecting rand from a view containing null
1. Initialization of random value by seed_random() has been
removed from Item_func_rand::fix_fields method.
2. The Item_func_rand::val_real method has been modified to
call seed_random() on the first evaluation of this method
if an argument is a function.
sql/item_func.h:
Bug #44768: SIGFPE crash when selecting rand from a view containing null
1. The Item_func_rand::first_eval has been added to trace
the first evaluation of the val_real method.
2. The Item_func_rand::cleanup method has been added to
cleanup the first_eval flag.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_func.cc | 20 | ||||
-rw-r--r-- | sql/item_func.h | 4 |
2 files changed, 18 insertions, 6 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index 6f40298f8cf..4bb61f4ef52 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2143,9 +2143,6 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref) if (!rand && !(rand= (struct rand_struct*) thd->stmt_arena->alloc(sizeof(*rand)))) return TRUE; - - if (args[0]->const_item()) - seed_random (args[0]); } else { @@ -2175,8 +2172,21 @@ void Item_func_rand::update_used_tables() double Item_func_rand::val_real() { DBUG_ASSERT(fixed == 1); - if (arg_count && !args[0]->const_item()) - seed_random (args[0]); + if (arg_count) + { + if (!args[0]->const_item()) + seed_random(args[0]); + else if (first_eval) + { + /* + Constantness of args[0] may be set during JOIN::optimize(), if arg[0] + is a field item of "constant" table. Thus, we have to evaluate + seed_random() for constant arg there but not at the fix_fields method. + */ + first_eval= FALSE; + seed_random(args[0]); + } + } return my_rnd(rand); } diff --git a/sql/item_func.h b/sql/item_func.h index 147dfcc9d36..e512c94efc1 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -696,14 +696,16 @@ public: class Item_func_rand :public Item_real_func { struct rand_struct *rand; + bool first_eval; // TRUE if val_real() is called 1st time public: - Item_func_rand(Item *a) :Item_real_func(a), rand(0) {} + Item_func_rand(Item *a) :Item_real_func(a), rand(0), first_eval(TRUE) {} Item_func_rand() :Item_real_func() {} double val_real(); const char *func_name() const { return "rand"; } bool const_item() const { return 0; } void update_used_tables(); bool fix_fields(THD *thd, Item **ref); + void cleanup() { first_eval= TRUE; Item_real_func::cleanup(); } private: void seed_random (Item * val); }; |