Bug #28810 Crash with huge negative decimal for Falcon and CSV
Submitted: 31 May 2007 15:56 Modified: 25 Jul 2007 3:22
Reporter: Peter Gulutzan Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: General Severity:S3 (Non-critical)
Version:5.1, 6.0.1-alpha-debug OS:Linux (SUSE 10 64-bit)
Assigned to: Ingo Strüwing CPU Architecture:Any
Tags: falcon

[31 May 2007 15:56] Peter Gulutzan
Description:
I create a Falcon table with a decimal(65) column.
I insert the largest possible number.
I try to insert the negative of the largest possible number.
Crash.

I do not see the program reaching ScaledBinary::putBinaryDecimal,
so I suppose this is not related to bug#28725 Falcon: crash with decimal.

ChangeSet@1.2525, 2007-05-31

How to repeat:
mysql> create table t (s1 decimal(65)) engine=falcon;
Query OK, 0 rows affected (0.39 sec)

mysql> insert into t values (99999999999999999999999999999999999999999999999999999999999999999);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t select -s1 from t;
ERROR 2013 (HY000): Lost connection to MySQL server during query
[31 May 2007 17:00] MySQL Verification Team
Thank you for the bug report. Verified as described on FC 6.0 32-bit.

mysql> insert into t select -s1 from t;
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql>
[5 Jun 2007 7:30] Hakan Küçükyılmaz
Related to Bug#28725
[18 Jun 2007 7:25] Christopher Powers
This bug will be addressed by WL#3923, Arbitrary Precision Division for Falcon BigInt.
[19 Jun 2007 18:02] Christopher Powers
The crash is caused by a fatal assertion in Field_new_decimal().
The assertion occurs because item->max_length == 67, which exceeds DECIMAL_MAX_PRECISION.

This does not appear to have any connection to the BigInt support in Falcon because the assertion occurs before the record is retrieved by the storage engine.

Also note that "select -s1 from t" and "insert into t values (-999...999)" succeed independently.

Windows stack at time of assertion (params abbreviated for clarity):

mysqld.exe!_NMSG_WRITE(int rterrnum=0x0000000a)  Line 198	C
mysqld.exe!abort()  Line 59 + 0x7 bytes	C
mysqld.exe!_wassert(const wchar_t * expr=0x00bead70, const wchar_t * filename=0x00bead54, unsigned int lineno=0x00000920)  Line 212	C
mysqld.exe!Field_new_decimal::Field_new_decimal(unsigned int len_arg=0x00000043,  ...)
mysqld.exe!create_tmp_field_from_item(THD * thd=0x01ea21d8, Item * item=0x01ed02f8, st_table * table=0x01ecbf88, ...)
mysqld.exe!create_tmp_field(THD * thd=0x01ea21d8, ...)
mysqld.exe!create_tmp_table(THD * thd=0x01ea21d8, TMP_TABLE_PARAM * param=0x01ed1694, List<Item> & fields={...}, ...)
mysqld.exe!JOIN::optimize()  Line 1371 + 0xa9 bytes
mysqld.exe!mysql_select(THD * thd=0x01ea21d8, Item *** rref_pointer_array=0x01ea3360,...)
mysqld.exe!handle_select(THD * thd=0x01ea21d8, st_lex * lex=0x01ea2f68, ...)
mysqld.exe!mysql_execute_command(THD * thd=0x01ea21d8)  Line 2753 + 0x19 bytes
mysqld.exe!mysql_parse(THD * thd=0x01ea21d8, const char * inBuf=0x01ecffe8, ...)
mysqld.exe!dispatch_command(enum_server_command command=COM_QUERY, ...)
mysqld.exe!do_command(THD * thd=0x01ea21d8)  Line 669 + 0x31 bytes
mysqld.exe!handle_one_connection(void * arg=0x01ea21d8)  Line 1091 + 0x9 bytes
mysqld.exe!pthread_start(void * param=0x01e8c138)  Line 62 + 0x9 bytes
mysqld.exe!_callthreadstart()  Line 293 + 0xf bytes
mysqld.exe!_threadstart(void * ptd=0x01ea5468)  Line 277
kernel32.dll!_BaseThreadStart@8()  + 0x37 bytes	

From create_tmp_field_from_item(). Note item->max_length == 67:

- item            0x01ed02f8
+ [Item_func_neg] {...}
+ __vfptr         0x00c2b9dc
  rsize           0
+ str_value       {Ptr=0x00000000 <Bad Ptr> str_length=0 Alloced_length=0 ...}
+ name            0x01ed03b0 "-s1"
+ orig_name       0x00000000 <Bad Ptr>
+ next            0x01ed0268 {field=0x01ed7cd0 result_field=0x01ed7cd0 item_equal=0x00000000 ...}
  max_length      67
  name_length     3
  marker          0
  decimals        0
  maybe_null      1 '?'
  null_value      0
  unsigned_flag   0
  with_sum_func   0
  fixed           1 '?'
  is_autogenerated_name    1 '?'
+ collation       {collation=0x00de4aa0 derivation=DERIVATION_COERCIBLE }
  with_subselect  0
  cmp_context     -1
[19 Jun 2007 19:17] Hakan Küçükyılmaz
Why does it not for MyISAM?

[18:51] root@test>create table t (s1 decimal(65)) engine myisam;
Query OK, 0 rows affected (0.01 sec)

[18:51] root@test>insert into t values
    -> (99999999999999999999999999999999999999999999999999999999999999999);
Query OK, 1 row affected (0.00 sec)

[18:51] root@test>insert into t select -s1 from t;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

[21:15] root@test>select * from t;
+--------------------------------------------------------------------+
| s1                                                                 |
+--------------------------------------------------------------------+
|  99999999999999999999999999999999999999999999999999999999999999999 |
| -99999999999999999999999999999999999999999999999999999999999999999 |
+--------------------------------------------------------------------+
[19 Jun 2007 19:19] Calvin Sun
The same test fails with CSV engine. According to Ingo, it is likely the case that the wrong field type (new decimal) has been selected by an upper layer.
[2 Jul 2007 15:06] Ingo Strüwing
It does not crash for MyISAM as it uses the 'system' join strategy (the table has only one row). Inserting two lines reproduces the crash for MyISAM too (the 'ALL' join strategy is used). I would say this bug is not engine specific.
[4 Jul 2007 16:22] Ingo Strüwing
http://lists.mysql.com/commits/30309

ChangeSet@1.2582, 2007-07-04 16:16:55+02:00, istruewing@chilla.local +6 -0
  Bug#28810 - Crash with huge negative decimal for Falcon and CSV
  
  Problem #1:
  
  Debug server crashed when inserting a negated decimal number of
  maximum precision (65): INSERT ... SELECT -column ...
  
  The problem was that the negation function added 1 to the column
  length for the sign unconditionally. When the source item was
  a signed field with maximum precision, the result was a field with
  one more than maximum. This triggered an assert.
  
  The fix is to avoid adding 1 to max_length when the argument of
  the negation function is a signed field . A signed field does
  already have space for the sign.
  
  Problem #2:
  
  The test case for CSV reported table corruption.
  Entering a negative number into a CSV table corrupted the table.
  
  The problem was that numbers were written to the CSV file without
  quoting, but when reading from the file, only fields starting
  with a digit were accepted unquoted.
  
  The fix is to accept reading of fields that start with a sign ('-'),
  followed by a digit unquoted too.
[5 Jul 2007 8:41] Sergei Golubchik
the second part of a patch is a duplicate of (already pushed) bug#29353
[5 Jul 2007 9:35] Ingo Strüwing
I can only guess that Sergei wants me to propose a new patch with the CSV fix stripped off.
[5 Jul 2007 10:34] 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/30364

ChangeSet@1.2582, 2007-07-05 12:33:13+02:00, istruewing@chilla.local +3 -0
  Bug#28810 - Crash with huge negative decimal for Falcon and CSV
  
  Debug server crashed when inserting a negated decimal number of
  maximum precision (65): INSERT ... SELECT -column ...
  
  The problem was that the negation function added 1 to the column
  length for the sign unconditionally. When the source item was
  a signed field with maximum precision, the result was a field with
  one more than maximum. This triggered an assert.
  
  The fix is to avoid adding 1 to max_length when the argument of
  the negation function is a signed field . A signed field does
  already have space for the sign.
[12 Jul 2007 14:18] Ingo Strüwing
Pushed to 6.0.1 (mysql-5.1-falcon).
The problem is fixed differently in 5.0 and 5.1 by the patch for Bug#29417 (debug asser on decimal).
[25 Jul 2007 3:22] Paul DuBois
Noted in 6.0.1 changelog.

For debug builds, the server crashed when inserting a negated DECIMAL
value of maximum precision (65 digits), such as for INSERT INTO ...
SELECT -col_val ...