Bug #24117 server crash on a FETCH with a cursor on a table which is not in the table cache
Submitted: 8 Nov 2006 23:51 Modified: 1 Feb 2007 1:03
Reporter: Shane Bester (Platinum Quality Contributor) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Stored Routines Severity:S2 (Serious)
Version:5.0.26,5.0.28 OS:Any (*)
Assigned to: Alexey Kopytov CPU Architecture:Any

[8 Nov 2006 23:51] Shane Bester
Description:
under high concurrency the server can crash when dealing with enum types.
if you insert a row containing an enum and select using a cursor within a stored procedure at the same time, server crashes.

5.0.26-standard :

0x817adf8 handle_segfault + 356
0x81668fc _ZN10Field_enum7val_strEP6StringS1_ + 132
0x8239f41 _Z10field_convP5FieldS0_ + 197
0x811070a _ZN10Item_field13save_in_fieldEP5Fieldb + 70
0x82712c8 _Z12sp_eval_exprP3THDP5FieldPP4Item + 128
0x8278930 _ZN24Select_fetch_into_spvars9send_dataER4ListI4ItemE + 120
0x826cc94 _ZN19Materialized_cursor5fetchEm + 104
0x827876c _ZN9sp_cursor5fetchEP3THDP4ListI11sp_variableE + 152
0x827585b _ZN15sp_instr_cfetch7executeEP3THDPj + 51
0x8271fe4 _ZN7sp_head7executeEP3THD + 812
0x82730bf _ZN7sp_head17execute_procedureEP3THDP4ListI4ItemE + 723
0x819441a _Z21mysql_execute_commandP3THD + 19570
0x8196a02 _Z11mysql_parseP3THDPcj + 306
0x818e2a6 _Z16dispatch_command19enum_server_commandP3THDPcj + 1182
Stack trace seems successful - bottom reached

How to repeat:
build and run the attached testcase.c, which is self-contained.

Suggested fix:
.
[8 Nov 2006 23:52] MySQL Verification Team
see top of file for example of how to build it using gcc

Attachment: testcase.c (text/x-csrc), 4.37 KiB.

[8 Nov 2006 23:56] MySQL Verification Team
stack from 5.0.28 debug build

Attachment: stacke_5.0.28.txt (plain/text, text), 1.06 KiB.

[9 Nov 2006 1:59] MySQL Verification Team
mysqld-debug.exe crash backtrace on 5.0.26

Attachment: 5.0.26_win_stack.txt (plain/text, text), 3.29 KiB.

[13 Nov 2006 12:03] MySQL Verification Team
The insert isn't needed to be run concurrently with calling the sp.  The table can be pre-populated before the time with 1000 records and launching the running 'call p1()' in 90 threads will still crash.
[30 Nov 2006 16:20] Alexey Kopytov
A much more simple testcase for this bug:

DROP TABLE IF EXISTS t1;
DROP PROCEDURE IF EXISTS p1;
CREATE TABLE t1(c1 ENUM('abc'));
INSERT INTO t1 VALUES('abc');
DELIMITER //
CREATE PROCEDURE p1()
BEGIN DECLARE t1c1 ENUM('abc');  DECLARE mycursor CURSOR FOR SELECT c1 FROM t1; OPEN mycursor;  FLUSH TABLES;  FETCH mycursor INTO t1c1; CLOSE mycursor; END //
DELIMITER ;
CALL p1();
[4 Dec 2006 10:42] 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/16370

ChangeSet@1.2334, 2006-12-04 13:41:51+03:00, kaa@polly.local +4 -0
  Fix for bug #24117 "server crash on a FETCH with a cursor on a table which is not in the table cache"
  
  Problem:
  When creating a temporary field for a temporary table in create_tmp_field_from_field(),
  a resulting field is created as an exact copy of an original one (in Field::new_field()).
  However, Field_enum and Field_set contain a pointer (typelib) to memory allocated in the
  parent table's MEM_ROOT, which under some circumstances may be deallocated later by the 
  time a temporary table is used.
  
  Solution:
  Override the new_field() method for Field_enum and Field_set and create a separate copy
  of the typelib structure in there.
[14 Dec 2006 18:00] 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/16974

ChangeSet@1.2334, 2006-12-14 20:58:07+03:00, kaa@polly.local +6 -0
  Fix for bug #24117 "server crash on a FETCH with a cursor on a table which is not in the table cache"
  
  Problem:
  When creating a temporary field for a temporary table in create_tmp_field_from_field(), a resulting field is created as an exact copy of an original one (in Field::new_field()). However, Field_enum and Field_set contain a pointer (typelib) to memory allocated in the parent table's MEM_ROOT, which under some circumstances may be deallocated later by the time a temporary table is used.
  
  Solution:
  Override the new_field() method for Field_enum and Field_set and create a separate copy of the typelib structure in there.
[31 Jan 2007 19:18] Chad MILLER
Available in 5.0.36, 5.1.15-beta.
[1 Feb 2007 1:03] Jon Stephens
Thank you for your bug report. This issue has been committed to our source repository of that product and will be incorporated into the next release.

If necessary, you can access the source repository and build the latest available version, including the bug fix. More information about accessing the source trees is available at

    http://dev.mysql.com/doc/en/installing-source.html

Documented fix in 5.0.36 and 5.1.15 changelogs.