summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorGleb Shchepa <gshchepa@mysql.com>2009-05-18 09:21:25 +0500
committerGleb Shchepa <gshchepa@mysql.com>2009-05-18 09:21:25 +0500
commit405bd2af117384e009c3feffe1fd7d9019bf9d2b (patch)
tree0cc46a52d78c3e50ef405932673b7269b7af6590 /sql
parentbaeac8762396a181440368c9413d617f0f49aacc (diff)
downloadmariadb-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.cc20
-rw-r--r--sql/item_func.h4
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);
};