[MDEV-28958] Crash when checking whether condition can be pushed into view Created: 2022-06-27  Updated: 2023-03-16  Resolved: 2023-03-16

Status: Closed
Project: MariaDB Server
Component/s: Optimizer
Affects Version/s: 10.7, 10.8, 10.9, 10.10, 10.11
Fix Version/s: 11.1.0, 10.11.3, 10.8.8, 10.9.6, 10.10.4

Type: Bug Priority: Critical
Reporter: Roel Van de Paar Assignee: Igor Babaev
Resolution: Fixed Votes: 0
Labels: not-10.3, not-10.4, not-10.5, not-10.6, pushdown_from_having, regression-10.7

Attachments: HTML File diff    

 Description   

CREATE TABLE c(c INT) ENGINE=InnoDB;
SELECT * FROM(SELECT * FROM c GROUP BY NOT c=c) AS c NATURAL JOIN c AS c GROUP BY c HAVING c=c OR c=c;

Leads to:

10.10.0 081a284712bb661349e2e3802077b12211cede3e (Optimized)

Core was generated by `/test/MD310522-mariadb-10.10.0-linux-x86_64-opt/bin/mysqld --no-defaults --core'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000055ae368d5e44 in Item::clear_extraction_flag (this=0x149bb20a4090)
    at /test/10.10_opt/sql/item.h:2664
[Current thread is 1 (Thread 0x149b98d48700 (LWP 3347048))]
(gdb) bt
#0  0x000055ae368d5e44 in Item::clear_extraction_flag (this=0x149bb20a4090) at /test/10.10_opt/sql/item.h:2664
#1  Item::check_pushable_cond (this=0x149bb20a4090, checker=(bool (Item::*)(Item * const, uchar *)) 0x55ae3662aec0 <Item::pushable_cond_checker_for_derived(unsigned char*)>, arg=0x149b5404b128 "\001") at /test/10.10_opt/sql/item.cc:7505
#2  0x000055ae368d5f99 in Item::check_pushable_cond (this=0x149b5401fa68, checker=<optimized out>, arg=0x149b5404b128 "\001") at /test/10.10_opt/sql/item.cc:7514
#3  0x000055ae368d5eea in Item::check_pushable_cond (this=this@entry=0x149b540220a8, checker=<optimized out>, arg=0x149b5404b128 "\001") at /test/10.10_opt/sql/item.cc:7514
#4  0x000055ae36629be1 in pushdown_cond_for_derived (thd=0x149b54000c58, cond=0x149b540220a8, derived=derived@entry=0x149b540129e0) at /test/10.10_opt/sql/sql_derived.cc:1538
#5  0x000055ae366e0b45 in JOIN::optimize_inner (this=0x149b54020458) at /test/10.10_opt/sql/sql_select.cc:2318
#6  0x000055ae366e3b13 in JOIN::optimize (this=this@entry=0x149b54020458) at /test/10.10_opt/sql/sql_select.cc:1845
#7  0x000055ae366e3bfe in mysql_select (thd=0x149b54000c58, tables=0x149b540129e0, fields=@0x149b54010ad8: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x149b54010dc8, last = 0x149b54010dc8, elements = 1}, <No data fields>}, conds=0x0, og_num=1, order=0x0, group=0x149b540140c8, having=0x149b5401fa68, proc_param=0x0, select_options=<optimized out>, result=0x149b54020430, unit=0x149b54004cb8, select_lex=0x149b54010838) at /test/10.10_opt/sql/sql_select.cc:5030
#8  0x000055ae366e4397 in handle_select (thd=thd@entry=0x149b54000c58, lex=lex@entry=0x149b54004be0, result=result@entry=0x149b54020430, setup_tables_done_option=setup_tables_done_option@entry=0) at /test/10.10_opt/sql/sql_select.cc:578
#9  0x000055ae366679b1 in execute_sqlcom_select (thd=0x149b54000c58, all_tables=0x149b540129e0) at /test/10.10_opt/sql/sql_parse.cc:6260
#10 0x000055ae3667552d in mysql_execute_command (thd=0x149b54000c58, is_called_from_prepared_stmt=<optimized out>) at /test/10.10_opt/sql/sql_parse.cc:3944
#11 0x000055ae36662bb5 in mysql_parse (rawbuf=<optimized out>, length=<optimized out>, parser_state=<optimized out>, thd=0x149b54000c58) at /test/10.10_opt/sql/sql_parse.cc:8036
#12 mysql_parse (thd=0x149b54000c58, rawbuf=<optimized out>, length=<optimized out>, parser_state=<optimized out>) at /test/10.10_opt/sql/sql_parse.cc:7958
#13 0x000055ae3666e6ca in dispatch_command (command=COM_QUERY, thd=0x149b54000c58, packet=<optimized out>, packet_length=<optimized out>, blocking=<optimized out>) at /test/10.10_opt/sql/sql_class.h:1364
#14 0x000055ae366705f2 in do_command (thd=0x149b54000c58, blocking=blocking@entry=true) at /test/10.10_opt/sql/sql_parse.cc:1407
#15 0x000055ae367868af in do_handle_one_connection (connect=<optimized out>, connect@entry=0x55ae39b31eb8, put_in_cache=put_in_cache@entry=true) at /test/10.10_opt/sql/sql_connect.cc:1418
#16 0x000055ae36786b8d in handle_one_connection (arg=0x55ae39b31eb8) at /test/10.10_opt/sql/sql_connect.cc:1312
#17 0x0000149bb1f88609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#18 0x0000149bb1b74133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

10.10.2 5deccac4aaf1be948a0ae10f40bb5f668ac37a4d (Debug)

Core was generated by `/test/MD190922-mariadb-10.10.2-linux-x86_64-dbg/bin/mysqld --no-defaults --core'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  Item::clear_extraction_flag (this=0x14dcb199d090)
    at /test/10.10_dbg/sql/item.h:2674
[Current thread is 1 (Thread 0x14dc9880d700 (LWP 620908))]
(gdb) bt
#0  Item::clear_extraction_flag (this=0x14dcb199d090) at /test/10.10_dbg/sql/item.h:2674
#1  Item::check_pushable_cond (this=0x14dcb199d090, checker=(bool (Item::*)(Item * const, uchar *)) 0x558ff487bd8a <Item::pushable_cond_checker_for_derived(unsigned char*)>, arg=0x14dc5806c5e8 "\001") at /test/10.10_dbg/sql/item.cc:7521
#2  0x0000558ff4be982e in Item::check_pushable_cond (this=0x14dc58027278, checker=<optimized out>, arg=0x14dc5806c5e8 "\001") at /test/10.10_dbg/sql/item.cc:7530
#3  0x0000558ff4be982e in Item::check_pushable_cond (this=this@entry=0x14dc58029920, checker=<optimized out>, arg=0x14dc5806c5e8 "\001") at /test/10.10_dbg/sql/item.cc:7530
#4  0x0000558ff487a5d6 in pushdown_cond_for_derived (thd=0x14dc58000d48, cond=0x14dc58029920, derived=derived@entry=0x14dc580153b0) at /test/10.10_dbg/sql/sql_derived.cc:1538
#5  0x0000558ff4958f15 in JOIN::optimize_inner (this=this@entry=0x14dc58027c68) at /test/10.10_dbg/sql/sql_select.cc:2339
#6  0x0000558ff49599f6 in JOIN::optimize (this=this@entry=0x14dc58027c68) at /test/10.10_dbg/sql/sql_select.cc:1863
#7  0x0000558ff4959ae9 in mysql_select (thd=thd@entry=0x14dc58000d48, tables=0x14dc580153b0, fields=@0x14dc580134a8: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x14dc58013798, last = 0x14dc58013798, elements = 1}, <No data fields>}, conds=0x0, og_num=1, order=0x0, group=0x14dc58016aa0, having=0x14dc58027278, proc_param=0x0, select_options=2164525824, result=0x14dc58027c40, unit=0x14dc58004f80, select_lex=0x14dc58013208) at /test/10.10_dbg/sql/sql_select.cc:5056
#8  0x0000558ff495a332 in handle_select (thd=thd@entry=0x14dc58000d48, lex=lex@entry=0x14dc58004ea8, result=result@entry=0x14dc58027c40, setup_tables_done_option=setup_tables_done_option@entry=0) at /test/10.10_dbg/sql/sql_select.cc:581
#9  0x0000558ff48c43e7 in execute_sqlcom_select (thd=thd@entry=0x14dc58000d48, all_tables=0x14dc580153b0) at /test/10.10_dbg/sql/sql_parse.cc:6261
#10 0x0000558ff48d0755 in mysql_execute_command (thd=thd@entry=0x14dc58000d48, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /test/10.10_dbg/sql/sql_parse.cc:3945
#11 0x0000558ff48be68d in mysql_parse (thd=thd@entry=0x14dc58000d48, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x14dc9880c330) at /test/10.10_dbg/sql/sql_parse.cc:8035
#12 0x0000558ff48cbcbf in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x14dc58000d48, packet=packet@entry=0x14dc5800adb9 "SELECT * FROM(SELECT * FROM c GROUP BY NOT c=c) AS c NATURAL JOIN c AS c GROUP BY c HAVING c=c OR c=c", packet_length=packet_length@entry=101, blocking=blocking@entry=true) at /test/10.10_dbg/sql/sql_class.h:1345
#13 0x0000558ff48ce3e2 in do_command (thd=0x14dc58000d48, blocking=blocking@entry=true) at /test/10.10_dbg/sql/sql_parse.cc:1407
#14 0x0000558ff4a30abd in do_handle_one_connection (connect=<optimized out>, connect@entry=0x558ff77ab1a8, put_in_cache=put_in_cache@entry=true) at /test/10.10_dbg/sql/sql_connect.cc:1416
#15 0x0000558ff4a30fc7 in handle_one_connection (arg=0x558ff77ab1a8) at /test/10.10_dbg/sql/sql_connect.cc:1318
#16 0x000014dcb1881609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#17 0x000014dcb146d133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Bug confirmed present in:
MariaDB: 10.7.5 (dbg), 10.7.5 (opt), 10.8.4 (dbg), 10.8.4 (opt), 10.9.2 (dbg), 10.9.2 (opt), 10.10.0 (dbg), 10.10.0 (opt)

Bug (or feature/syntax) confirmed not present in:
MariaDB: 10.3.36 (dbg), 10.3.36 (opt), 10.4.26 (dbg), 10.4.26 (opt), 10.5.17 (dbg), 10.5.17 (opt), 10.6.9 (dbg), 10.6.9 (opt)
MySQL: 5.5.62 (dbg), 5.5.62 (opt), 5.6.51 (dbg), 5.6.51 (opt), 5.7.38 (dbg), 5.7.38 (opt), 8.0.29 (dbg), 8.0.29 (opt)



 Comments   
Comment by Roel Van de Paar [ 2022-07-13 ]

Secondary testcase

CREATE TABLE c(c CHAR) ENGINE=InnoDB;
SELECT * FROM(SELECT * FROM c GROUP BY NOT c=c / c % 0)AS c NATURAL JOIN c AS c GROUP BY c HAVING c=c OR c=c;

Leads to:

10.10.0 081a284712bb661349e2e3802077b12211cede3e (Debug)

Core was generated by `/test/MD310522-mariadb-10.10.0-linux-x86_64-dbg/bin/mysqld --no-defaults --core'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  Item::clear_extraction_flag (this=0x14f25cbb4090)
    at /test/10.10_dbg/sql/item.h:2664
[Current thread is 1 (Thread 0x14f213dfe700 (LWP 3169405))]
(gdb) bt
#0  Item::clear_extraction_flag (this=0x14f25cbb4090) at /test/10.10_dbg/sql/item.h:2664
#1  Item::check_pushable_cond (this=0x14f25cbb4090, checker=(bool (Item::*)(Item * const, uchar *)) 0x55aecf0f8a74 <Item::pushable_cond_checker_for_derived(unsigned char*)>, arg=0x14f1fc072308 "\001") at /test/10.10_dbg/sql/item.cc:7505
#2  0x000055aecf460afa in Item::check_pushable_cond (this=0x14f1fc024710, checker=<optimized out>, arg=0x14f1fc072308 "\001") at /test/10.10_dbg/sql/item.cc:7514
#3  0x000055aecf460afa in Item::check_pushable_cond (this=this@entry=0x14f1fc026e88, checker=<optimized out>, arg=0x14f1fc072308 "\001") at /test/10.10_dbg/sql/item.cc:7514
#4  0x000055aecf0f72c0 in pushdown_cond_for_derived (thd=0x14f1fc000db8, cond=0x14f1fc026e88, derived=derived@entry=0x14f1fc016218) at /test/10.10_dbg/sql/sql_derived.cc:1538
#5  0x000055aecf1d3971 in JOIN::optimize_inner (this=this@entry=0x14f1fc025100) at /test/10.10_dbg/sql/sql_select.cc:2318
#6  0x000055aecf1d4452 in JOIN::optimize (this=this@entry=0x14f1fc025100) at /test/10.10_dbg/sql/sql_select.cc:1845
#7  0x000055aecf1d4545 in mysql_select (thd=thd@entry=0x14f1fc000db8, tables=0x14f1fc016218, fields=@0x14f1fc014008: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x14f1fc0142f8, last = 0x14f1fc0142f8, elements = 1}, <No data fields>}, conds=0x0, og_num=1, order=0x0, group=0x14f1fc017900, having=0x14f1fc024710, proc_param=0x0, select_options=2147748608, result=0x14f1fc0250d8, unit=0x14f1fc004fd8, select_lex=0x14f1fc013d68) at /test/10.10_dbg/sql/sql_select.cc:5030
#8  0x000055aecf1d4d8e in handle_select (thd=thd@entry=0x14f1fc000db8, lex=lex@entry=0x14f1fc004f00, result=result@entry=0x14f1fc0250d8, setup_tables_done_option=setup_tables_done_option@entry=0) at /test/10.10_dbg/sql/sql_select.cc:578
#9  0x000055aecf140b5e in execute_sqlcom_select (thd=thd@entry=0x14f1fc000db8, all_tables=0x14f1fc016218) at /test/10.10_dbg/sql/sql_parse.cc:6260
#10 0x000055aecf14ce70 in mysql_execute_command (thd=thd@entry=0x14f1fc000db8, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /test/10.10_dbg/sql/sql_parse.cc:3944
#11 0x000055aecf13ae3a in mysql_parse (thd=thd@entry=0x14f1fc000db8, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x14f213dfd470) at /test/10.10_dbg/sql/sql_parse.cc:8036
#12 0x000055aecf148422 in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x14f1fc000db8, packet=packet@entry=0x14f1fc00b6d9 "SELECT * FROM(SELECT * FROM c GROUP BY NOT c=c / c % 0)AS c NATURAL JOIN c AS c GROUP BY c HAVING c=c OR c=c", packet_length=packet_length@entry=108, blocking=blocking@entry=true) at /test/10.10_dbg/sql/sql_class.h:1364
#13 0x000055aecf14ab2c in do_command (thd=0x14f1fc000db8, blocking=blocking@entry=true) at /test/10.10_dbg/sql/sql_parse.cc:1407
#14 0x000055aecf2aa3c0 in do_handle_one_connection (connect=<optimized out>, connect@entry=0x55aed1601fb8, put_in_cache=put_in_cache@entry=true) at /test/10.10_dbg/sql/sql_connect.cc:1418
#15 0x000055aecf2aa8c9 in handle_one_connection (arg=0x55aed1601fb8) at /test/10.10_dbg/sql/sql_connect.cc:1312
#16 0x000014f25ca98609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#17 0x000014f25c684133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Bug confirmed present in:
MariaDB: 10.7.5 (dbg), 10.7.5 (opt), 10.8.4 (dbg), 10.8.4 (opt), 10.9.2 (dbg), 10.9.2 (opt), 10.10.0 (dbg)

Bug (or feature/syntax) confirmed not present in:
MariaDB: 10.3.36 (dbg), 10.3.36 (opt), 10.4.26 (dbg), 10.4.26 (opt), 10.5.17 (dbg), 10.5.17 (opt), 10.6.9 (dbg), 10.6.9 (opt), 10.10.0 (opt)
MySQL: 5.5.62 (dbg), 5.5.62 (opt), 5.6.51 (dbg), 5.6.51 (opt), 5.7.38 (dbg), 5.7.38 (opt), 8.0.29 (dbg), 8.0.29 (opt)

Comment by Sergei Petrunia [ 2022-11-10 ]

According to Johnston, still reproducible on current 10.7.

Comment by Sergei Petrunia [ 2022-11-10 ]

Johnston, please try with valgrind (or a *san) build. Maybe it will immediately show we're trying to access free'd memory.

Comment by Rex Johnston [ 2022-11-10 ]

I can confirm that it's not in 10.5 too. Will try valgrind first.

Comment by Rex Johnston [ 2022-11-14 ]

Valgrind build fails...

[ 97%] Building CXX object sql/CMakeFiles/sql.dir/opt_split.cc.o
/usr/bin/ld: libmariadbd.a(password_reuse_check.c.o): in function `report_sql_error':
/home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:78: undefined reference to `server_mysql_error'
/usr/bin/ld: /home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:78: undefined reference to `server_mysql_errno'
/usr/bin/ld: libmariadbd.a(password_reuse_check.c.o): in function `create_table':
/home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:94: undefined reference to `server_mysql_real_query'
/usr/bin/ld: libmariadbd.a(password_reuse_check.c.o): in function `run_query_with_table_creation':
/home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:123: undefined reference to `server_mysql_real_query'
/usr/bin/ld: /home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:125: undefined reference to `server_mysql_errno'
/usr/bin/ld: /home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:143: undefined reference to `server_mysql_real_query'
/usr/bin/ld: libmariadbd.a(password_reuse_check.c.o): in function `validate':
/home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:179: undefined reference to `server_mysql_init'
/usr/bin/ld: /home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:220: undefined reference to `server_mysql_close'
/usr/bin/ld: /home/rex/src/mariadb/server/plugin/password_reuse_check/password_reuse_check.c:226: undefined reference to `server_mysql_close'
[ 97%] Building CXX object sql/CMakeFiles/sql.dir/rowid_filter.cc.o

etc.

Investigating.

Comment by Roel Van de Paar [ 2022-11-14 ]

Johnston Try ASAN + UBSAN build (they can be merged) and/or MSAN build.

Comment by Rex Johnston [ 2022-11-15 ]

Have got valgrind build working. At the crash point...

(gdb) where
#0  0x0000000000adf516 in Item::clear_extraction_flag (this=0x48580a0) at /home/rex/src/mariadb/server.borked/sql/item.h:2688
#1  0x0000000000f2d40b in Item::check_pushable_cond (this=0x48580a0, checker=
    (bool (Item::*)(Item * const, uchar *)) 0xadf51e <Item::pushable_cond_checker_for_derived(unsigned char*)>, arg=0x38eccaa8 "\001")
    at /home/rex/src/mariadb/server.borked/sql/item.cc:7516
#2  0x0000000000f2d4b3 in Item::check_pushable_cond (this=0x38eb1fe0, checker=
    (bool (Item::*)(Item * const, uchar *)) 0xadf51e <Item::pushable_cond_checker_for_derived(unsigned char*)>, arg=0x38eccaa8 "\001")
    at /home/rex/src/mariadb/server.borked/sql/item.cc:7525
#3  0x0000000000f2d4b3 in Item::check_pushable_cond (this=0x38ecfed0, checker=
    (bool (Item::*)(Item * const, uchar *)) 0xadf51e <Item::pushable_cond_checker_for_derived(unsigned char*)>, arg=0x38eccaa8 "\001")
    at /home/rex/src/mariadb/server.borked/sql/item.cc:7525
#4  0x0000000000adec64 in pushdown_cond_for_derived (thd=0x345412b8, cond=0x38ecfed0, derived=0x38eaf3c0) at /home/rex/src/mariadb/server.borked/sql/sql_derived.cc:1538
#5  0x0000000000ba1693 in JOIN::optimize_inner (this=0x38ecb080) at /home/rex/src/mariadb/server.borked/sql/sql_select.cc:2350
#6  0x0000000000b9f9d0 in JOIN::optimize (this=0x38ecb080) at /home/rex/src/mariadb/server.borked/sql/sql_select.cc:1871
#7  0x0000000000bab58d in mysql_select (thd=0x345412b8, tables=0x38eaf3c0, fields=..., conds=0x0, og_num=1, order=0x0, group=0x38eb1210, having=0x38eb1fe0, proc_param=0x0, 
    select_options=2164525824, result=0x38eca980, unit=0x345456f8, select_lex=0x38eac5d0) at /home/rex/src/mariadb/server.borked/sql/sql_select.cc:5096
#8  0x0000000000b9a7b4 in handle_select (thd=0x345412b8, lex=0x34545620, result=0x38eca980, setup_tables_done_option=0) at /home/rex/src/mariadb/server.borked/sql/sql_select.cc:581
#9  0x0000000000b44ad1 in execute_sqlcom_select (thd=0x345412b8, all_tables=0x38eaf3c0) at /home/rex/src/mariadb/server.borked/sql/sql_parse.cc:6263
#10 0x0000000000b3c00b in mysql_execute_command (thd=0x345412b8, is_called_from_prepared_stmt=false) at /home/rex/src/mariadb/server.borked/sql/sql_parse.cc:3947
#11 0x0000000000b49453 in mysql_parse (thd=0x345412b8, rawbuf=0x38eabc40 "SELECT * FROM(SELECT * FROM c GROUP BY NOT c=c) AS c NATURAL JOIN c AS c GROUP BY c HAVING c=c OR c=c", 
    length=101, parser_state=0x376a0140) at /home/rex/src/mariadb/server.borked/sql/sql_parse.cc:7998
#12 0x0000000000b363f0 in dispatch_command (command=COM_QUERY, thd=0x345412b8, 
    packet=0x3454d1a9 "SELECT * FROM(SELECT * FROM c GROUP BY NOT c=c) AS c NATURAL JOIN c AS c GROUP BY c HAVING c=c OR c=c", packet_length=101, blocking=true)
    at /home/rex/src/mariadb/server.borked/sql/sql_parse.cc:1894
#13 0x0000000000b34e33 in do_command (thd=0x345412b8, blocking=true) at /home/rex/src/mariadb/server.borked/sql/sql_parse.cc:1407
#14 0x0000000000d0a0bc in do_handle_one_connection (connect=0x3453f418, put_in_cache=true) at /home/rex/src/mariadb/server.borked/sql/sql_connect.cc:1416
#15 0x0000000000d09e2c in handle_one_connection (arg=0x3453f418) at /home/rex/src/mariadb/server.borked/sql/sql_connect.cc:1318
#16 0x0000000001202cfc in pfs_spawn_thread (arg=0x34540bd8) at /home/rex/src/mariadb/server.borked/storage/perfschema/pfs.cc:2201
#17 0x0000000004eafea7 in start_thread (arg=<optimized out>) at pthread_create.c:477
#18 0x00000000052f9aef in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) p this
$2 = (Item * const) 0x48580a0
(gdb) monitor who_points_at 0x48580a0
==18974== Searching for pointers to 0x48580a0
==18974== *0x28e5368 points at 0x48580a0
 Address 0x28e5368 is 0 bytes inside data symbol "Item_true"
==18974== *0x3769f038 points at 0x48580a0
 Address 0x3769f038 is on thread 26's stack
==18974== *0x3769f068 points at 0x48580a0
 Address 0x3769f068 is on thread 26's stack
 in frame #1, created by Item::check_pushable_cond(bool (Item::*)(unsigned char*), unsigned char*) (item.cc:7515)
==18974== *0x3769f0f0 points at 0x48580a0
 Address 0x3769f0f0 is on thread 26's stack
 in frame #2, created by Item::check_pushable_cond(bool (Item::*)(unsigned char*), unsigned char*) (item.cc:7515)
==18974== *0x38eb2128 points at 0x48580a0
 Address 0x38eb2128 is 56 bytes inside a block of size 64 alloc'd
==18974==    at 0x483877F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==18974==    by 0x18B6123: my_malloc (my_malloc.c:90)
==18974==    by 0x18A68ED: alloc_root (my_alloc.c:287)
==18974==    by 0x9B85EA: Sql_alloc::operator new(unsigned long, st_mem_root*) (sql_alloc.h:37)
==18974==    by 0x9B87AF: base_list::push_back(void*, st_mem_root*) (sql_list.h:195)
==18974==    by 0xA05504: List<Item>::push_back(Item*, st_mem_root*) (sql_list.h:505)
==18974==    by 0xF527BD: Item_cond::Item_cond(THD*, Item*, Item*) (item_cmpfunc.cc:4880)
==18974==    by 0xBF3C1B: Item_cond_or::Item_cond_or(THD*, Item*, Item*) (item_cmpfunc.h:3564)
==18974==    by 0xE478F1: MYSQLparse(THD*) (sql_yacc.yy:9082)
==18974==    by 0xB4EC0D: parse_sql(THD*, Parser_state*, Object_creation_ctx*, bool) (sql_parse.cc:10390)
==18974==    by 0xB4929A: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:7950)
==18974==    by 0xB363EF: dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) (sql_parse.cc:1894)
==18974== *0x38eb21a8 points at 0x48580a0
 Address 0x38eb21a8 is 56 bytes inside a block of size 64 alloc'd
==18974==    at 0x483877F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==18974==    by 0x18B6123: my_malloc (my_malloc.c:90)
==18974==    by 0x18A68ED: alloc_root (my_alloc.c:287)
==18974==    by 0x9B85EA: Sql_alloc::operator new(unsigned long, st_mem_root*) (sql_alloc.h:37)
==18974==    by 0x9B87AF: base_list::push_back(void*, st_mem_root*) (sql_list.h:195)
==18974==    by 0xA05504: List<Item>::push_back(Item*, st_mem_root*) (sql_list.h:505)
==18974==    by 0xF527DE: Item_cond::Item_cond(THD*, Item*, Item*) (item_cmpfunc.cc:4881)
==18974==    by 0xBF3C1B: Item_cond_or::Item_cond_or(THD*, Item*, Item*) (item_cmpfunc.h:3564)
==18974==    by 0xE478F1: MYSQLparse(THD*) (sql_yacc.yy:9082)
==18974==    by 0xB4EC0D: parse_sql(THD*, Parser_state*, Object_creation_ctx*, bool) (sql_parse.cc:10390)
==18974==    by 0xB4929A: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:7950)
==18974==    by 0xB363EF: dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) (sql_parse.cc:1894)
==18974== tid 26 register RAX pointing at 0x48580a0
==18974== tid 26 register RDI pointing at 0x48580a0

Comment by Sergei Petrunia [ 2022-11-28 ]

Valgrind error I'm observing:

==7302== Process terminating with default action of signal 11 (SIGSEGV)
==7302==  Bad permissions for mapped region at address 0x403C102
==7302==    at 0xA7604E: Item::clear_extraction_flag() (item.h:2674)
==7302==    by 0xEDCE18: Item::check_pushable_cond(bool (Item::*)(unsigned char*), unsigned char*) (item.cc:7521)
==7302==    by 0xEDCEBF: Item::check_pushable_cond(bool (Item::*)(unsigned char*), unsigned char*) (item.cc:7530)
==7302==    by 0xEDCEBF: Item::check_pushable_cond(bool (Item::*)(unsigned char*), unsigned char*) (item.cc:7530)
==7302==    by 0xA7575A: pushdown_cond_for_derived(THD*, Item*, TABLE_LIST*) (sql_derived.cc:1538)

Indeed, the Item_true is a global object which somehow was put into a read-only memory.

And Rex's fix is to make Item_func_eq::build_equal_items allocate a new object which is private to this query and is writable. This is correct.

My concern is, are there any other scenarios where Item tree has a pointer to this global Item_true object? If there are, we can get other similar bugs...
Should we

  • Stop using the global Item_int altogether?
  • Make pushdown_cond_for_derived() and Item::clear_extraction_flag() to never modify global read-only Item objects? (We could do that, but what should item->get_extraction_flag() return for global read-only item objects?
Comment by Sergei Petrunia [ 2022-11-28 ]

Discussed this with Monty. We should try to avoid setting/clearing flags like extraction flag in constant items. One needs to take a look at why pushdown_cond_for_derived() does it.

It looks like it should be sufficient to set/clear such flags only for direct children of Item_cond_and/Item_cond_or objects. Items that are constant should not be direct children of Item_cond_and/item_cond_or (as they can be removed in that case).

Comment by Michael Widenius [ 2022-11-28 ]

The issue is that we are calling clear_extraction_flag on all items, including const items and other items that we are not going to mark or have to mark.

It is a not a good idea to mark all items, including sub items, as the marking and cleanup can become very expensive in the long run. Better to avoid marking all items (just marking AND and OR items can be ok)

One can easily avoid the issue with Item_true/Item_false as these are ALWAYS top level items. Checking for basic_const_item() at function start/function call avoids this issue

Comment by Michael Widenius [ 2022-11-28 ]

Here is a suggested patch that fixes the issue:
diff

Comment by Sergei Petrunia [ 2022-11-29 ]

As far as I understood from the optimizer call this week, Igor will clarify something about which way this should be fixed... (Please re-assign accordingly if it is not correct)

Comment by Igor Babaev [ 2022-11-30 ]

The following test case is more meaningful and causes the same problem:

create table t1 (c1 int);
insert into t1 values (3), (7), (1), (3), (1), (3);
create table t2 (c2 int);
insert into t2 values (3), (5), (7), (3);
create view v1 as select * from t1 group by c1;
create view v2 as select c1 as a, c2 as b from v1,t2 where c1=c2;
select * from v2 group by a,b having a=b or b > a+10;

Comment by Igor Babaev [ 2022-11-30 ]

If we are not allowed to use the field 'marker' for basis_const_items let's not to use this field for such items:

  bool depends_only_on(table_map view_map) 
  { return get_extraction_flag() & MARKER_FULL_EXTRACTION; }   
  int get_extraction_flag() const
  { 
    if (basic_const_item())
      return MARKER_FULL_EXTRACTION;
    else
      return marker & MARKER_EXTRACTION_MASK;
  }
  void set_extraction_flag(int16 flags)
  {
    if (!basic_const_item())
    {
      marker= marker & ~MARKER_EXTRACTION_MASK;
      marker|= flags;
    }
  }
  void clear_extraction_flag()
  {
    if (!basic_const_item())
      marker= marker & ~MARKER_EXTRACTION_MASK;
  }

Comment by Oleksandr Byelkin [ 2023-02-06 ]

OK to push.

Comment by Igor Babaev [ 2023-03-16 ]

A fix for this bug was pushed into 10.8

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