Bug #44768 SIGFPE crash when selecting rand from a view containing null
Submitted: 10 May 2009 20:45 Modified: 26 Jun 2009 2:27
Reporter: Shane Bester (Platinum Quality Contributor) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: DML Severity:S1 (Critical)
Version:5.1.30, 5.1.34, 5.1.35 OS:Linux (32-bit fc8)
Assigned to: Gleb Shchepa CPU Architecture:Any
Tags: crash, rand, regression, SIGFPE

[10 May 2009 20:45] Shane Bester
Description:
SIGFPE crash when selecting rand from a view containing null. 5.1.35 output (cut):

Program received signal SIGFPE, Arithmetic exception.
[Switching to Thread -1271317616 (LWP 9207)]
0x081fd6c3 in my_rnd (rand_st=0x9cc93c8) at password.c:101
101       rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
Current language:  auto; currently c

(gdb) bt
 my_rnd (rand_st=0x9cc93c8) at password.c:101
 Item_func_rand::val_real (this=0x9cc84c8) at item_func.cc:2180
 Item::send at item.cc:5350
 select_send::send_data  at sql_class.cc:1587
 end_send  at sql_select.cc:11976
 in do_select at sql_select.cc:10854
 JOIN::exec at sql_select.cc:2199
 mysql_select at sql_select.cc:2378
 handle_select  at sql_select.cc:268
 execute_sqlcom_select at sql_parse.cc:5009
 mysql_execute_command at sql_parse.cc:2211
 mysql_parse at sql_parse.cc:5929
 dispatch_command at sql_parse.cc:1216
 do_command (thd=0x9ca86d8) at sql_parse.cc:857
 handle_one_connection (arg=0x9ca86d8) at sql_connect.cc:1115
 start_thread () from /lib/i686/nosegneg/libpthread.so.0

How to repeat:
create or replace view `vt` as select null as `a`;
select rand(`a`) from `vt` limit 1;
[10 May 2009 21:11] MySQL Verification Team
5.0 gives correct response: ERROR 1210 (HY000): Incorrect arguments to RAND.
so, this is a regression.
[14 May 2009 5:36] Gleb Shchepa
Analysis:

This issue is a regression of the bugfix for bug #6172.

The problem is wider: not only views returning NULL are affected, but any "constant" table (i.e. a table returning only 1 row):

1. select rand(a) from (select null as a) b;

or even

2. CREATE TABLE t1 (i INT);
   INSERT INTO t1 VALUES (1);
   SELECT RAND(i) FROM t1;

This problem is caused in Item_func_rand::val_real() 
by uninitialized memory:

2175	double Item_func_rand::val_real()
2176	{
2177	  DBUG_ASSERT(fixed == 1);
2178	  if (arg_count && !args[0]->const_item())
2179	    seed_random (args[0]);
2180	  return my_rnd(rand);
2181	}

(gdb) p/x *rand
$1 = {
  seed1 = 0x8f8f8f8f, 
  seed2 = 0x8f8f8f8f, 
  max_value = 0x8f8f8f8f, 
  max_value_dbl = 0x0
}

The root cause is constantness of a field item arg[0]:
at Item_func_rand:val_real() it is constant, so it supposes
that seed_random() was called at Item_func_rand::fix_fields():

2147	    if (args[0]->const_item())
2148	      seed_random (args[0]);

but there args[0]->const_item() is false! So it never call
seed_random() for this item, and *Item_func_rand::rand is
uninitialized.

The constant state of a field item arg[0] is changed because
of an execution order:

1. Item_func_rand::fix_fields() is called from JOIN::prepare,
at that moment tables in the FROM list are not constant;

2. JOIN::optimize() --> make_join_statistics() --> join_read_const_table()
marks some tables as constant.

3. JOIN:execute() calls Item_func_rand::var_real(), where arg[0]->const_item() is changed.
[14 May 2009 13:36] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/74052

2880 Gleb Shchepa	2009-05-14
      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.
[15 May 2009 9:08] Georgi Kodinov
Gleb,

Check what our docs say : 
http://dev.mysql.com/doc/refman/5.1/en/mathematical-functions.html#function_rand.

Basically if a constant argument is specified we need to initialize only once (as this is documented). 
And if non-constant initializer is specified (a column name etc) it will initialize on each evaluation.
[18 May 2009 5:19] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/74331

2883 Gleb Shchepa	2009-05-18
      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.
[28 May 2009 8:17] Bugs System
Pushed into 5.1.36 (revid:joro@sun.com-20090528073639-yohsb4q1jzg7ycws) (version source revid:kristofer.pettersson@sun.com-20090518083544-lm5vcjzm0id10y12) (merge vers: 5.1.36) (pib:6)
[2 Jun 2009 16:52] Paul DuBois
Noted in 5.1.36 changelog.

Selecting RAND(N) function where N is a column of a constant table
(table with a single row) failed with a SIGFPE signal. 

Setting report to NDI pending push into 6.0.x.
[17 Jun 2009 19:24] Bugs System
Pushed into 5.4.4-alpha (revid:alik@sun.com-20090616183122-chjzbaa30qopdra9) (version source revid:gshchepa@mysql.com-20090518050211-88uzx48nvazgyhh6) (merge vers: 6.0.12-alpha) (pib:11)
[26 Jun 2009 2:27] Paul DuBois
Noted in 5.4.4 changelog.
[12 Aug 2009 22:28] Paul DuBois
Noted in 5.4.2 changelog because next 5.4 version will be 5.4.2 and not 5.4.4.
[15 Aug 2009 1:47] Paul DuBois
Ignore previous comment about 5.4.2.
[26 Aug 2009 13:46] Bugs System
Pushed into 5.1.37-ndb-7.0.8 (revid:jonas@mysql.com-20090826132541-yablppc59e3yb54l) (version source revid:jonas@mysql.com-20090826132541-yablppc59e3yb54l) (merge vers: 5.1.37-ndb-7.0.8) (pib:11)
[26 Aug 2009 13:46] Bugs System
Pushed into 5.1.37-ndb-6.3.27 (revid:jonas@mysql.com-20090826105955-bkj027t47gfbamnc) (version source revid:jonas@mysql.com-20090826105955-bkj027t47gfbamnc) (merge vers: 5.1.37-ndb-6.3.27) (pib:11)
[26 Aug 2009 13:48] Bugs System
Pushed into 5.1.37-ndb-6.2.19 (revid:jonas@mysql.com-20090825194404-37rtosk049t9koc4) (version source revid:jonas@mysql.com-20090825194404-37rtosk049t9koc4) (merge vers: 5.1.37-ndb-6.2.19) (pib:11)
[27 Aug 2009 16:32] Bugs System
Pushed into 5.1.35-ndb-7.1.0 (revid:magnus.blaudd@sun.com-20090827163030-6o3kk6r2oua159hr) (version source revid:jonas@mysql.com-20090826132541-yablppc59e3yb54l) (merge vers: 5.1.37-ndb-7.0.8) (pib:11)
[7 Oct 2009 19:34] Paul DuBois
The 5.4 fix has been pushed to 5.4.2.