[MDEV-17020] Assertion `length > 0' failed in ptr_compare upon ORDER BY with bad conversion Created: 2018-08-19  Updated: 2018-10-15  Resolved: 2018-10-15

Status: Closed
Project: MariaDB Server
Component/s: Server
Affects Version/s: 10.0, 10.1, 10.2
Fix Version/s: 10.0.37, 10.3.11, 10.1.37, 10.2.19

Type: Bug Priority: Major
Reporter: Elena Stepanova Assignee: Varun Gupta (Inactive)
Resolution: Fixed Votes: 0
Labels: None


 Description   

SET sql_mode= '';
CREATE TABLE t1 (pk INT PRIMARY KEY);
INSERT INTO t1 VALUES (1),(2);
SELECT * FROM t1 ORDER BY 'foo', CONVERT(pk, CHAR(0)) LIMIT 2;
 
# Cleanup
DROP TABLE t1;

10.0 bcc677bb7

mysqld: /data/src/10.0/mysys/ptr_cmp.c:94: ptr_compare: Assertion `length > 0' failed.
180819 17:32:54 [ERROR] mysqld got signal 6 ;
 
#7  0x00007fec92194ee2 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
#8  0x0000000000e2966d in ptr_compare (compare_length=0x7fec94262f48, a=0x7fec8a859a38, b=0x7fec8a859a30) at /data/src/10.0/mysys/ptr_cmp.c:94
#9  0x0000000000e2a66a in queue_insert (queue=0x7fec94262f60, element=0x7fec8a859a38 "L\232\205\212\354\177") at /data/src/10.0/mysys/queues.c:203
#10 0x000000000083a5ef in Bounded_queue<unsigned char, unsigned char>::push (this=0x7fec94262f40, element=0x7fec94262e10 "") at /data/src/10.0/sql/bounded_queue.h:190
#11 0x0000000000836e58 in find_all_keys (param=0x7fec94263000, select=0x7fec8abb13b0, fs_info=0x7fec94262f90, buffpek_pointers=0x7fec94263220, tempfile=0x7fec94263080, pq=0x7fec94262f40, found_rows=0x7fec942634c8) at /data/src/10.0/sql/filesort.cc:817
#12 0x00000000008357e4 in filesort (thd=0x7fec8c2a2070, table=0x7fec8a89e470, sortorder=0x7fec8abb1900, s_length=1, select=0x7fec8abb13b0, max_rows=2, sort_positions=false, examined_rows=0x7fec942634d0, found_rows=0x7fec942634c8) at /data/src/10.0/sql/filesort.cc:297
#13 0x00000000006b514c in create_sort_index (thd=0x7fec8c2a2070, join=0x7fec8a8facf0, order=0x7fec8a8fabd8, filesort_limit=2, select_limit=2, is_order_by=true) at /data/src/10.0/sql/sql_select.cc:20996
#14 0x0000000000689f34 in JOIN::exec_inner (this=0x7fec8a8facf0) at /data/src/10.0/sql/sql_select.cc:3093
#15 0x00000000006875fe in JOIN::exec (this=0x7fec8a8facf0) at /data/src/10.0/sql/sql_select.cc:2409
#16 0x000000000068a9a0 in mysql_select (thd=0x7fec8c2a2070, rref_pointer_array=0x7fec8c2a63a0, tables=0x7fec8a8fa2c8, wild_num=1, fields=..., conds=0x0, og_num=2, order=0x7fec8a8fa970, group=0x0, having=0x0, proc_param=0x0, select_options=2147748608, result=0x7fec8a8facd0, unit=0x7fec8c2a5a08, select_lex=0x7fec8c2a60f8) at /data/src/10.0/sql/sql_select.cc:3348
#17 0x0000000000680a14 in handle_select (thd=0x7fec8c2a2070, lex=0x7fec8c2a5940, result=0x7fec8a8facd0, setup_tables_done_option=0) at /data/src/10.0/sql/sql_select.cc:377
#18 0x0000000000654f07 in execute_sqlcom_select (thd=0x7fec8c2a2070, all_tables=0x7fec8a8fa2c8) at /data/src/10.0/sql/sql_parse.cc:5301
#19 0x000000000064d45d in mysql_execute_command (thd=0x7fec8c2a2070) at /data/src/10.0/sql/sql_parse.cc:2557
#20 0x0000000000657d64 in mysql_parse (thd=0x7fec8c2a2070, rawbuf=0x7fec8a8fa088 "SELECT * FROM t1 ORDER BY 'foo', CONVERT(pk, CHAR(0)) LIMIT 2", length=61, parser_state=0x7fec94264640) at /data/src/10.0/sql/sql_parse.cc:6637
#21 0x000000000064a684 in dispatch_command (command=COM_QUERY, thd=0x7fec8c2a2070, packet=0x7fec8d7e5071 "SELECT * FROM t1 ORDER BY 'foo', CONVERT(pk, CHAR(0)) LIMIT 2", packet_length=61) at /data/src/10.0/sql/sql_parse.cc:1300
#22 0x0000000000649984 in do_command (thd=0x7fec8c2a2070) at /data/src/10.0/sql/sql_parse.cc:1003
#23 0x000000000076acdc in do_handle_one_connection (thd_arg=0x7fec8c2a2070) at /data/src/10.0/sql/sql_connect.cc:1377
#24 0x000000000076aa4e in handle_one_connection (arg=0x7fec8c2a2070) at /data/src/10.0/sql/sql_connect.cc:1292
#25 0x0000000000accef0 in pfs_spawn_thread (arg=0x7fec8c1a2370) at /data/src/10.0/storage/perfschema/pfs.cc:1861
#26 0x00007fec93e98494 in start_thread (arg=0x7fec94265700) at pthread_create.c:333
#27 0x00007fec9225193f in clone () from /lib/x86_64-linux-gnu/libc.so.6

Reproducible on 10.0, 10.1, 10.2, with at least InnoDB and MyISAM.
Couldn't reproduce on 10.3



 Comments   
Comment by Varun Gupta (Inactive) [ 2018-08-30 ]

Some investigations

* thread #2, stop reason = step over
    frame #0: 0x0000000100fbd064 mysqld`ptr_compare(compare_length=0x0000700005eb4a08, a=0x00006100000102b8, b=0x00006100000102b0) at ptr_cmp.c:94
   91  	  reg3 int length= *compare_length;
   92  	  reg1 uchar *first,*last;
   93  	
-> 94  	  DBUG_ASSERT(length > 0);
   95  	  first= *a; last= *b;
   96  	  while (--length)
   97  	  {
Target 0: (mysqld) stopped.
(lldb) p length
(int) $1 = 0
(lldb) p compare_length
(size_t *) $2 = 0x0000700005eb4a08
(lldb) p *compare_length
(size_t) $3 = 0

The stacktrace is

(lldb) bt
* thread #2, stop reason = step over
  * frame #0: 0x0000000100fbd064 mysqld`ptr_compare(compare_length=0x0000700005eb4a08, a=0x00006100000102b8, b=0x00006100000102b0) at ptr_cmp.c:94
    frame #1: 0x0000000100fbfbcc mysqld`queue_insert(queue=<unavailable>, element=<unavailable>) at queues.c:203
    frame #2: 0x000000010006c669 mysqld`find_all_keys(param=0x0000700005eb4950, select=0x00006290000647e0, fs_info=0x0000700005eb4ab0, buffpek_pointers=0x0000700005eb4740, tempfile=0x0000700005eb4530, pq=0x0000700005eb4a00, found_rows=<unavailable>) at filesort.cc:817
    frame #3: 0x0000000100068798 mysqld`filesort(thd=<unavailable>, table=<unavailable>, sortorder=<unavailable>, s_length=<unavailable>, select=<unavailable>, max_rows=<unavailable>, sort_positions=<unavailable>, examined_rows=0x0000700005eb4bf0, found_rows=0x0000700005eb4c10) at filesort.cc:292
    frame #4: 0x000000010054153d mysqld`create_sort_index(thd=0x000062a00005a270, join=0x000062500003f5e8, order=0x0000625000000000, filesort_limit=<unavailable>, select_limit=<unavailable>, is_order_by=true) at sql_select.cc:20994
    frame #5: 0x0000000100548c18 mysqld`JOIN::exec_inner(this=<unavailable>) at sql_select.cc:3088
    frame #6: 0x00000001005466ed mysqld`JOIN::exec(this=0x000062500003f5e8) at sql_select.cc:2409
    frame #7: 0x000000010051611d mysqld`mysql_select(thd=0x000062a00005a270, rref_pointer_array=<unavailable>, tables=<unavailable>, wild_num=<unavailable>, fields=<unavailable>, conds=<unavailable>, og_num=<unavailable>, order=<unavailable>, group=<unavailable>, having=<unavailable>, proc_param=<unavailable>, select_options=<unavailable>, result=<unavailable>, unit=<unavailable>, select_lex=<unavailable>) at sql_select.cc:3348
    frame #8: 0x0000000100515d13 mysqld`handle_select(thd=0x000062a00005a270, lex=0x000062a00005db40, result=<unavailable>, setup_tables_done_option=<unavailable>) at sql_select.cc:365
    frame #9: 0x000000010049f51c mysqld`execute_sqlcom_select(thd=0x000062a00005a270, all_tables=0x000062500003ebc8) at sql_parse.cc:5301
    frame #10: 0x0000000100491b8c mysqld`mysql_execute_command(thd=<unavailable>) at sql_parse.cc:2557
    frame #11: 0x000000010048eaf3 mysqld`mysql_parse(thd=0x000062a00005a270, rawbuf=<unavailable>, length=<unavailable>, parser_state=0x0000700005eb72f0) at sql_parse.cc:6637
    frame #12: 0x0000000100489f43 mysqld`dispatch_command(command=<unavailable>, thd=<unavailable>, packet="?u, packet_length=46177) at sql_parse.cc:1300
    frame #13: 0x000000010048d86b mysqld`do_command(thd=0x000062a00005a270) at sql_parse.cc:1003
    frame #14: 0x00000001006ff407 mysqld`do_handle_one_connection(thd_arg=<unavailable>) at sql_connect.cc:1377
    frame #15: 0x00000001006fee5d mysqld`::handle_one_connection(arg=0x000062a00005a270) at sql_connect.cc:1292
    frame #16: 0x00007fff73c99661 libsystem_pthread.dylib`_pthread_body + 340
    frame #17: 0x00007fff73c9950d libsystem_pthread.dylib`_pthread_start + 377
    frame #18: 0x00007fff73c98bf9 libsystem_pthread.dylib`thread_start + 13

Comment by Varun Gupta (Inactive) [ 2018-08-30 ]

The issue is maybe_null is set for CONVERT(pk, CHAR(0)) to be true on 10.2.

bool Item_str_func::fix_fields(THD *thd, Item **ref)
{
  bool res= Item_func::fix_fields(thd, ref);
  /*
    In Item_str_func::check_well_formed_result() we may set null_value
    flag on the same condition as in test() below.
  */
  maybe_null= maybe_null || thd->is_strict_mode();
  return res;
}

So the sql_mode has different default values in different version
Picking from the documentation:

Since MariaDB 10.2.4, SQL_MODE is by default set to 
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO.
In earlier versions of MariaDB 10.2, and since MariaDB 10.1.7, SQL_MODE is by default set to
NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER. 
For earlier versions of MariaDB 10.1, and MariaDB 10.0 and before, no default is set.

Comment by Varun Gupta (Inactive) [ 2018-08-30 ]

Patch
http://lists.askmonty.org/pipermail/commits/2018-August/012859.html

Comment by Varun Gupta (Inactive) [ 2018-09-13 ]

Feedback from psergey
http://lists.askmonty.org/pipermail/commits/2018-September/012918.html

Comment by Varun Gupta (Inactive) [ 2018-09-13 ]

New Patch:
http://lists.askmonty.org/pipermail/commits/2018-September/012928.html

Another solution could be to have a new compare function to handle zerolength sortkeys

Comment by Varun Gupta (Inactive) [ 2018-09-18 ]

Patch
http://lists.askmonty.org/pipermail/commits/2018-September/012943.html

Comment by Sergei Petrunia [ 2018-10-11 ]

Ok to push

Generated at Thu Feb 08 08:33:19 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.