[MDEV-30159] Client can crash the server with a mysql_list_fields("view") call Created: 2022-12-05  Updated: 2023-08-15  Resolved: 2023-07-20

Status: Closed
Project: MariaDB Server
Component/s: OTHER
Affects Version/s: 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 10.10, 10.11
Fix Version/s: 10.4.31, 10.5.22, 10.6.15, 10.9.8, 10.10.6, 10.11.5, 11.0.3, 11.1.2, 11.2.1

Type: Bug Priority: Critical
Reporter: Sergei Petrunia Assignee: Oleksandr Byelkin
Resolution: Fixed Votes: 2
Labels: None

Attachments: File test1.cc    

 Description   

This is based on a support issue.

A Connector/C client can crash the server based by issuing a

 mysql_list_fields("v1")

call, where v1 is a view with a certain definition.

Trying equivalent (or are they similar?) commands from command line client:

desc v1;

does not cause a crash, expected result is produced.

create table t1 (
  name  varchar(100),
  typ varchar(100)
);
insert into t1 select seq,seq from seq_1_to_10;
insert into t1 select '', 'value' from seq_1_to_2;
 
create table t2 (
  servername varchar(100)
);
insert into t2 select seq from seq_1_to_10;
 
create view v1 as 
select * from t2
where 
   `t2`.`servername` regexp (  select 
                                  group_concat(`t1`.`name` separator '|') 
                               from `t1` 
                               where `t1`.`typ` 
                               like 'value') 
;

Crashes like so:

Thread 14 "mysqld" received signal SIGABRT, Aborted.
(gdb) wher
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140736891541056) at pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140736891541056) at pthread_kill.c:80
#2  __GI___pthread_kill (threadid=140736891541056, signo=signo@entry=6) at pthread_kill.c:91
#3  0x00007ffff7635476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff761b7b7 in __GI_abort () at abort.c:79
#5  0x00007ffff761b6db in __assert_fail_base (fmt=0x7ffff77cf770 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x555556f826d8 "table_share->tmp_table != NO_TMP_TABLE || m_lock_type != 2", file=0x555556f80c90 "/home/psergey/dev-git/10.7/sql/handler.cc", line=3407, function=<optimized out>) at assert.c:92
#6  0x00007ffff762ce26 in __GI___assert_fail (assertion=0x555556f826d8 "table_share->tmp_table != NO_TMP_TABLE || m_
lock_type != 2", file=0x555556f80c90 "/home/psergey/dev-git/10.7/sql/handler.cc", line=3407, function=0x555556f826b0 "int handler::ha_rnd_next(uchar*)") at assert.c:101
#7  0x000055555630ff77 in handler::ha_rnd_next (this=0x7fffac93b5f0, buf=0x7fffac93bde0 "\377") at /home/psergey/dev-git/10.7/sql/handler.cc:3407
#8  0x0000555555de4ac6 in rr_sequential (info=0x7fffac940458) at /home/psergey/dev-git/10.7/sql/records.cc:519
#9  0x0000555555dce777 in READ_RECORD::read_record (this=0x7fffac940458) at /home/psergey/dev-git/10.7/sql/records.h:81
#10 0x0000555555fd1040 in join_init_read_record (tab=0x7fffac940390) at /home/psergey/dev-git/10.7/sql/sql_select.cc:22364
#11 0x0000555555fce950 in sub_select (join=0x7fffac944450, join_tab=0x7fffac940390, end_of_records=false) at /home/psergey/dev-git/10.7/sql/sql_select.cc:21367
#12 0x0000555555fcdd50 in do_select (join=0x7fffac944450, procedure=0x0) at /home/psergey/dev-git/10.7/sql/sql_select.cc:20913
#13 0x0000555555f9fdfd in JOIN::exec_inner (this=0x7fffac944450) at /home/psergey/dev-git/10.7/sql/sql_select.cc:4794
#14 0x0000555555f9ee37 in JOIN::exec (this=0x7fffac944450) at /home/psergey/dev-git/10.7/sql/sql_select.cc:4572
#15 0x00005555564290d8 in subselect_single_select_engine::exec (this=0x7fffac01bcb0) at /home/psergey/dev-git/10.7/sql/item_subselect.cc:4095
#16 0x000055555641b526 in Item_subselect::exec (this=0x7fffac01bb20) at /home/psergey/dev-git/10.7/sql/item_subselect.cc:811
#17 0x000055555641d980 in Item_singlerow_subselect::val_str (this=0x7fffac01bb20, str=0x7fffdc6d2410) at /home/psergey/dev-git/10.7/sql/item_subselect.cc:1477
#18 0x000055555636c567 in Regexp_processor_pcre::compile (this=0x7fffac01bde0, item=0x7fffac01bb20, send_error=true)at /home/psergey/dev-git/10.7/sql/item_cmpfunc.cc:6083
#19 0x000055555636cb26 in Regexp_processor_pcre::fix_owner (this=0x7fffac01bde0, owner=0x7fffac01bd30, subject_arg=0x7fffac019270, pattern_arg=0x7fffac01bb20) at /home/psergey/dev-git/10.7/sql/item_cmpfunc.cc:6189
#20 0x000055555636cc3e in Item_func_regex::fix_length_and_dec (this=0x7fffac01bd30) at /home/psergey/dev-git/10.7/sql/item_cmpfunc.cc:6210
#21 0x000055555639771c in Item_func::fix_fields (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item_func.cc:362
#22 0x0000555555df30be in Item::fix_fields_if_needed (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item.h:1147
#23 0x0000555555df30f7 in Item::fix_fields_if_needed_for_scalar (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item.h:1156
#24 0x0000555555e8175b in Item::fix_fields_if_needed_for_bool (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item.h:1160
#25 0x0000555555e7de16 in setup_conds (thd=0x7fffac000d48, tables=0x7fffac018940, leaves=..., conds=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/sql_base.cc:8540
#26 0x0000555555f8fdc0 in setup_without_group (thd=0x7fffac000d48, ref_pointer_array=..., tables=0x7fffac018940, leaves=..., fields=..., all_fields=..., conds=0x7fffac9442b0, order=0x0, group=0x0, win_specs=..., win_funcs=..., hidden_group_fields=0x7fffac944177, reserved=0x7fffac01827c) at /home/psergey/dev-git/10.7/sql/sql_select.cc:858 
#27 0x0000555555f92ec2 in JOIN::prepare (this=0x7fffac943e60, tables_init=0x7fffac018940, conds_init=0x7fffac01bd30,og_num=0, order_init=0x0, skip_order_by=false, group_init=0x0, having_init=0x0, proc_param_init=0x0, select_lex_arg
=0x7fffac017ec0, unit_arg=0x7fffac016228) at /home/psergey/dev-git/10.7/sql/sql_select.cc:1439
#28 0x00005555560715a2 in st_select_lex_unit::prepare_join (this=0x7fffac016228, thd_arg=0x7fffac000d48, sl=0x7fffac017ec0, tmp_result=0x7fffac93e6f0, additional_options=0, is_union_select=false) at /home/psergey/dev-git/10.7/sql/sql_union.cc:1103
#29 0x0000555556072ef9 in st_select_lex_unit::prepare (this=0x7fffac016228, derived_arg=0x7fffdc6d4460, sel_result=0x7fffac93e6f0, additional_options=0) at /home/psergey/dev-git/10.7/sql/sql_union.cc:1496
#30 0x0000555555ec6e49 in mysql_derived_prepare (thd=0x7fffac000d48, lex=0x7fffac005080, derived=0x7fffdc6d4460) at /home/psergey/dev-git/10.7/sql/sql_derived.cc:855
#31 0x0000555555ec4fdd in mysql_handle_derived (lex=0x7fffac005080, phases=3) at /home/psergey/dev-git/10.7/sql/sql_derived.cc:123
#32 0x0000555555e7501e in open_normal_and_derived_tables (thd=0x7fffac000d48, tables=0x7fffdc6d4460, flags=1024, dt_phases=3) at /home/psergey/dev-git/10.7/sql/sql_base.cc:5368
#33 0x0000555555ff7dc9 in mysqld_list_fields (thd=0x7fffac000d48, table_list=0x7fffdc6d4460, wild=0x7fffac013390 "") at /home/psergey/dev-git/10.7/sql/sql_show.cc:1498
#34 0x0000555555f24dbb in dispatch_command (command=COM_FIELD_LIST, thd=0x7fffac000d48, packet=0x7fffac00ac0c "", packet_length=3, blocking=true) at /home/psergey/dev-git/10.7/sql/sql_parse.cc:2087
#35 0x0000555555f22cc0 in do_command (thd=0x7fffac000d48, blocking=true) at /home/psergey/dev-git/10.7/sql/sql_parse.cc:1407
#36 0x000055555610b961 in do_handle_one_connection (connect=0x555558abb248, put_in_cache=true) at /home/psergey/dev-git/10.7/sql/sql_connect.cc:1416

The assert is hit here:

int handler::ha_rnd_next(uchar *buf)
{
  int result;
  DBUG_ENTER("handler::ha_rnd_next");
  DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
              m_lock_type != F_UNLCK);

The reason:

3407      DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
(gdb) p table_share
$1 = (TABLE_SHARE *) 0x7fffac027c80
(gdb) p table_share->tmp_table
$2 = NO_TMP_TABLE
(gdb) p m_lock_type
$3 = 2
(gdb) p F_UNLCK
$4 = 2



 Comments   
Comment by Sergei Petrunia [ 2023-02-27 ]

Reproducible on current 10.5,

commit d3f35aa47bc3ee0c9b2798555f9a79057895809a (HEAD -> 10.5, origin/10.5)
Author: Marko Mäkelä <marko.makela@mariadb.com>
Date:   Thu Feb 16 10:16:38 2023 +0200
 
    MDEV-30552 fixup: Fix the test for non-debug

Comment by Sergei Petrunia [ 2023-02-28 ]

Let's look the stack trace:

#6  0x00007ffff762ce26 in __GI___assert_fail (assertion=0x555556f826d8 "table_share->tmp_table != NO_TMP_TABLE || m_lock_type != 2", file=0x555556f80c90 "/home/psergey/dev-git/10.7/sql/handler.cc", line=3407, function=0x555556f826b0 "int handler::ha_rnd_next(uchar*)") at assert.c:101
#7  0x000055555630ff77 in handler::ha_rnd_next (this=0x7fffac93b5f0, buf=0x7fffac93bde0 "\377") at /home/psergey/dev-git/10.7/sql/handler.cc:3407
#8  0x0000555555de4ac6 in rr_sequential (info=0x7fffac940458) at /home/psergey/dev-git/10.7/sql/records.cc:519

Assertion fails when we're trying to read the table.
My initial guess is that the reason is that the table is not locked properly.

..
#14 0x0000555555f9ee37 in JOIN::exec (this=0x7fffac944450) at /home/psergey/dev-git/10.7/sql/sql_select.cc:4572
#15 0x00005555564290d8 in subselect_single_select_engine::exec (this=0x7fffac01bcb0) at /home/psergey/dev-git/10.7/sql/item_subselect.cc:4095

We're reading the table because we're computing a scalar-context subquery.

#16 0x000055555641b526 in Item_subselect::exec (this=0x7fffac01bb20) at /home/psergey/dev-git/10.7/sql/item_subselect.cc:811
#17 0x000055555641d980 in Item_singlerow_subselect::val_str (this=0x7fffac01bb20, str=0x7fffdc6d2410) at /home/psergey/dev-git/10.7/sql/item_subselect.cc:1477
#18 0x000055555636c567 in Regexp_processor_pcre::compile (this=0x7fffac01bde0, item=0x7fffac01bb20, send_error=true)at /home/psergey/dev-git/10.7/sql/item_cmpfunc.cc:6083
#19 0x000055555636cb26 in Regexp_processor_pcre::fix_owner (this=0x7fffac01bde0, owner=0x7fffac01bd30, subject_arg=0x7fffac019270, pattern_arg=0x7fffac01bb20) at /home/psergey/dev-git/10.7/sql/item_cmpfunc.cc:6189

which is an argument to REGEXP function.

the subquery can only be:

  `t2`.`servername regexp (  select .... )

and we do that while we're at PREPARE stage:

#20 0x000055555636cc3e in Item_func_regex::fix_length_and_dec (this=0x7fffac01bd30) at /home/psergey/dev-git/10.7/sql/item_cmpfunc.cc:6210
#21 0x000055555639771c in Item_func::fix_fields (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item_func.cc:362
#22 0x0000555555df30be in Item::fix_fields_if_needed (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item.h:1147
#23 0x0000555555df30f7 in Item::fix_fields_if_needed_for_scalar (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item.h:1156
#24 0x0000555555e8175b in Item::fix_fields_if_needed_for_bool (this=0x7fffac01bd30, thd=0x7fffac000d48, ref=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/item.h:1160
#25 0x0000555555e7de16 in setup_conds (thd=0x7fffac000d48, tables=0x7fffac018940, leaves=..., conds=0x7fffac9442b0) at /home/psergey/dev-git/10.7/sql/sql_base.cc:8540
#26 0x0000555555f8fdc0 in setup_without_group (thd=0x7fffac000d48, ref_pointer_array=..., tables=0x7fffac018940, leaves=..., fields=..., all_fields=..., conds=0x7fffac9442b0, order=0x0, group=0x0, win_specs=..., win_funcs=..., hidden_group_fields=0x7fffac944177, reserved=0x7fffac01827c) at /home/psergey/dev-git/10.7/sql/sql_select.cc:858 
#27 0x0000555555f92ec2 in JOIN::prepare (this=0x7fffac943e60, tables_init=0x7fffac018940, conds_init=0x7fffac01bd30,og_num=0, order_init=0x0, skip_order_by=false, group_init=0x0, having_init=0x0, proc_param_init=0x0, select_lex_arg
=0x7fffac017ec0, unit_arg=0x7fffac016228) at /home/psergey/dev-git/10.7/sql/sql_select.cc:1439
#28 0x00005555560715a2 in st_select_lex_unit::prepare_join (this=0x7fffac016228, thd_arg=0x7fffac000d48, sl=0x7fffac017ec0, tmp_result=0x7fffac93e6f0, additional_options=0, is_union_select=false) at /home/psergey/dev-git/10.7/sql/sql_union.cc:1103
#29 0x0000555556072ef9 in st_select_lex_unit::prepare (this=0x7fffac016228, derived_arg=0x7fffdc6d4460, sel_result=0x7fffac93e6f0, additional_options=0) at /home/psergey/dev-git/10.7/sql/sql_union.cc:1496
#30 0x0000555555ec6e49 in mysql_derived_prepare (thd=0x7fffac000d48, lex=0x7fffac005080, derived=0x7fffdc6d4460) at /home/psergey/dev-git/10.7/sql/sql_derived.cc:855
#31 0x0000555555ec4fdd in mysql_handle_derived (lex=0x7fffac005080, phases=3) at /home/psergey/dev-git/10.7/sql/sql_derived.cc:123
#32 0x0000555555e7501e in open_normal_and_derived_tables (thd=0x7fffac000d48, tables=0x7fffdc6d4460, flags=1024, dt_phases=3) at /home/psergey/dev-git/10.7/sql/sql_base.cc:5368
#33 0x0000555555ff7dc9 in mysqld_list_fields (thd=0x7fffac000d48, table_list=0x7fffdc6d4460, wild=0x7fffac013390 "") at /home/psergey/dev-git/10.7/sql/sql_show.cc:1498

I think, it is wrong that we try to compute a subquery at the PREPARE stage.

Comment by Oleksandr Byelkin [ 2023-07-07 ]

The test suite as it should be:

static void test_mdev_30159()
{
  MYSQL_RES *result;
  int rc;
 
  myheader("test_mdev_30159");
 
  rc= mysql_query(mysql, "create table t1 ("
                          "  name  varchar(100),"
                          "  typ varchar(100)"
                          ")");
  myquery(rc);
  rc= mysql_query(mysql, "insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),"
                          "(6,6),(7,7),(8,8),(9,9),(10,10)");
  myquery(rc);
  rc= mysql_query(mysql, "insert into t1 values ('', 'value'),('', 'value')");
  myquery(rc);
  rc= mysql_query(mysql, "create table t2 ("
                         "  servername varchar(100)"
                         ")");
  myquery(rc);
  rc= mysql_query(mysql, "insert into t2 values (1),(2),(3),(4),(5),"
                          "(6),(7),(8),(9),(10)");
  myquery(rc);
  rc= mysql_query(mysql, "create view v1 as"
                         "  select * from t2"
                         "    where"
                         "      `t2`.`servername` regexp (  select"
                         "          group_concat(`t1`.`name` separator '|')"
                         "          from `t1`"
                         "          where `t1`.`typ`"
                         "          like 'value')");
  myquery(rc);
 
  result= mysql_list_fields(mysql, "v1", NULL);
  mytest(result);
 
  rc= mysql_query(mysql, "drop view v1");
  myquery(rc);
  rc= mysql_query(mysql, "drop table t1, t2");
  myquery(rc);
}

Comment by Oleksandr Byelkin [ 2023-07-07 ]

psergei what make you thinks that it is 10.5 bug? I can releat it on 10.4

Comment by Oleksandr Byelkin [ 2023-07-14 ]

commit e0ae8df7ec02cbb9a663fa4663c0585bcd081294 (HEAD -> bb-10.4-MDEV-30159, origin/bb-10.4-MDEV-30159)
Author: Oleksandr Byelkin <sanja@mariadb.com>
Date:   Fri Jul 14 14:51:09 2023 +0200
 
    MDEV-30159: Client can crash the server with a mysql_list_fields("view") call
    
    Do not get value of expensive constants.

Comment by Alexander Barkov [ 2023-07-14 ]

https://github.com/MariaDB/server/commit/e0ae8df7ec02cbb9a663fa4663c0585bcd081294
is ok to push.

Thanks.

Generated at Thu Feb 08 10:14:06 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.