Bug #114657 BUG REPORT: MySQL 8.0.32+ Crashes when Stored Proc with Nested Queries Does a Co
Submitted: 16 Apr 15:42 Modified: 17 Apr 10:13
Reporter: Nicholas Othieno (OCA) Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:8.0.36 OS:Any
Assigned to: CPU Architecture:Any

[16 Apr 15:42] Nicholas Othieno
Description:
Introduction

It has been observed that MySQL 8.0.32 and higher crash when a stored proc is run that takes input parameters and compares at least one of these input parameters against a field in a nested query. For all the cases observed for this issue, the queries run fine in MySQL 5.7, but once the customer upgraded to 8.0.32+, they started experiencing crashes. We have a reproducible test case, but unfortunately our customer has not given us consent to publicly share this reproducible test case. We will therefore provide an analysis of the issue based on investigations using GDB/rr.

Detailed description

Queries that are known to crash are similar to the below:

CREATE DEFINER=`user1`@`localhost` PROCEDURE `db1`.`sp1`(IN param1 int, IN param2 int, IN param3 int, IN param4 int, IN param5 bigint)
BEGIN
      DECLARE EXIT HANDLER FOR SQLEXCEPTION
      BEGIN
            GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE,
            @errno = MYSQL_ERRNO,
            @text = MESSAGE_TEXT;
            SET @full_error = CONCAT("ERROR ", @errno, " (", @sqlstate, "): ", @text);
            SELECT
              @full_error;
       END;
SELECT SUM(c1alias) FROM
(SELECT COUNT(*) AS c1alias FROM t1 t1alias
         JOIN t2 t2alias
     ON t1alias.f2 = t2alias.f2
     WHERE t1alias.f3 = param1  <---This causes the crash
     AND t1alias.f3 IN (SELECT f3 FROM t3 t3alias WHERE  t3alias.f3 = t1alias.f3)) alias1;
END

From our investigation, we observed that a query similar to the above crashes the MySQL system if the same query is run against 2 different databases but in the same thread sequentially. For example:

CALL db1.sp1(74222,1,0,102,1000623);CALL db2.sp1(74222,1,0,102,1000623);

Switching back to the details observed in the crash generated by our customer, we see the following stack trace when the segmentation fault occurs:

(rr) bt
#0 0x0000559f8d69c55e in Item_cache::walk (this=0x7fbac47b2328, processor=&virtual Item::check_column_privileges(unsigned char*), walk=enum_walk::PREFIX, arg=0x7fbac4694a70 "\220pR\222\237U")
at /github/MySQL/mysql-server/sql/item.cc:9580
#1 0x0000559f8d6a493b in Item_ref::walk (this=0x7fbac47b23f0, processor=&virtual Item::check_column_privileges(unsigned char*), walk=enum_walk::PREFIX, arg=0x7fbac4694a70 "\220pR\222\237U")
at /github/MySQL/mysql-server/sql/item.h:5847
#2 0x0000559f8d719985 in Item_func::walk (this=0x7fbac47b2500, processor=&virtual table offset 752, walk=enum_walk::PREFIX, argument=0x7fbac4694a70 "\220pR\222\237U")
at /github/MySQL/mysql-server/sql/item_func.cc:617
#3 0x0000559f8d719985 in Item_func::walk (this=0x7fbac47b26b8, processor=&virtual table offset 752, walk=enum_walk::PREFIX, argument=0x7fbac4694a70 "\220pR\222\237U")
at /github/MySQL/mysql-server/sql/item_func.cc:617
#4 0x0000559f8d6c1fda in Item_cond::walk (this=0x7fbac47b27b0, processor=&virtual table offset 752, walk=enum_walk::PREFIX, arg=0x7fbac4694a70 "\220pR\222\237U")
at /github/MySQL/mysql-server/sql/item_cmpfunc.cc:5744
#5 0x0000559f8d2ae25d in Query_block::check_column_privileges (this=0x7fbac47ab530, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_select.cc:2046
#6 0x0000559f8d2ae9f1 in Query_block::check_privileges_for_subqueries (this=0x7fbac47a77f0, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_select.cc:2145
#7 0x0000559f8d2ae67a in Query_block::check_column_privileges (this=0x7fbac47a77f0, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_select.cc:2079
#8 0x0000559f8d2ae9f1 in Query_block::check_privileges_for_subqueries (this=0x7fbac47a2a00, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_select.cc:2145
#9 0x0000559f8d2ae67a in Query_block::check_column_privileges (this=0x7fbac47a2a00, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_select.cc:2079
#10 0x0000559f8d2abfd5 in Sql_cmd_select::check_privileges (this=0x7fbac47b0f58, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_select.cc:1163
#11 0x0000559f8d2aa983 in Sql_cmd_dml::execute (this=0x7fbac47b0f58, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_select.cc:732
#12 0x0000559f8d21f6b9 in mysql_execute_command (thd=0x7fbac4694a70, first_level=false) at /github/MySQL/mysql-server/sql/sql_parse.cc:4721
#13 0x0000559f8d0d93d1 in sp_instr_stmt::exec_core (this=0x7fbac47b11e0, thd=0x7fbac4694a70, nextp=0x7fba918e5bc4) at /github/MySQL/mysql-server/sql/sp_instr.cc:985
#14 0x0000559f8d0d7f2f in sp_lex_instr::reset_lex_and_exec_core (this=0x7fbac47b11e0, thd=0x7fbac4694a70, nextp=0x7fba918e5bc4, open_tables=false)
at /github/MySQL/mysql-server/sql/sp_instr.cc:461
#15 0x0000559f8d0d8a89 in sp_lex_instr::validate_lex_and_execute_core (this=0x7fbac47b11e0, thd=0x7fbac4694a70, nextp=0x7fba918e5bc4, open_tables=false)
at /github/MySQL/mysql-server/sql/sp_instr.cc:745
#16 0x0000559f8d0d90a9 in sp_instr_stmt::execute (this=0x7fbac47b11e0, thd=0x7fbac4694a70, nextp=0x7fba918e5bc4) at /github/MySQL/mysql-server/sql/sp_instr.cc:911
...

By looking at frame 0 we see that the crash occurs due to the example variable being dereferenced:

(rr) frame 0
#0 0x0000559f8d69c55e in Item_cache::walk (this=0x7fbac47b2328, processor=&virtual Item::check_column_privileges(unsigned char*), walk=enum_walk::PREFIX, arg=0x7fbac4694a70 "\220pR\222\237U")
at /github/MySQL/mysql-server/sql/item.cc:9580
9580 (example && example→walk(processor, walk, arg)) ||

The context of the example variable is shown below:

 9578 bool Item_cache::walk(Item_processor processor, enum_walk walk, uchar arg) {
 9579   return ((walk & enum_walk::PREFIX) && (this→processor)(arg)) ||
 9580          (example && example→walk(processor, walk, arg)) ||      <----- example is a non-null pointer that is pointing to invalid data as can be seen below.
 9581          ((walk & enum_walk::POSTFIX) && (this→*processor)(arg));
 9582 }

When we look at the contents of the Item object that example is pointing to, we find that they are invalid, having been filled with the value 0x8f repeatedly:

(rr) p example
$11 = (Item *) 0x7fbac5269ac0
(rr) p *example
$12 = {<Parse_tree_node_tmpl<Parse_context>> = {_vptr.Parse_tree_node_tmpl = 0x8f8f8f8f8f8f8f8f, contextualized = 143}, next_free = 0x8f8f8f8f8f8f8f8f, str_value = {
    m_ptr = 0x8f8f8f8f8f8f8f8f <error: Cannot access memory at address 0x8f8f8f8f8f8f8f8f>, m_length = 10344644715844964239, m_charset = 0x8f8f8f8f8f8f8f8f, m_alloced_length = 2408550287, m_is_alloced = 143}, 
  collation = {collation = 0x8f8f8f8f8f8f8f8f, derivation = 2408550287, repertoire = 2408550287}, item_name = {<Name_string> = {<Simple_cstring> = {
        m_str = 0x8f8f8f8f8f8f8f8f <error: Cannot access memory at address 0x8f8f8f8f8f8f8f8f>, m_length = 10344644715844964239}, <No data fields>}, m_is_autogenerated = 143}, 
  orig_name = {<Name_string> = {<Simple_cstring> = {m_str = 0x8f8f8f8f8f8f8f8f <error: Cannot access memory at address 0x8f8f8f8f8f8f8f8f>, m_length = 10344644715844964239}, <No data fields>}, 
    m_is_autogenerated = 143}, max_length = 2408550287, marker = 2408550287, cmp_context = -1886417009, m_ref_count = 2408550287, m_abandoned = 143, is_parser_item = 143, is_expensive_cache = -113 '\217', 
  m_data_type = 143 '\217', fixed = 143, decimals = 143 '\217', m_nullable = 143, null_value = 143, unsigned_flag = 143, m_is_window_function = 143, hidden = 143, m_in_check_constraint_exec_ctx = 143, 
  static PROP_SUBQUERY = 1 '\001', static PROP_STORED_PROGRAM = 2 '\002', static PROP_AGGREGATION = 4 '\004', static PROP_WINDOW_FUNCTION = 8 '\b', static PROP_ROLLUP_EXPR = 16 '\020', 
  static PROP_GROUPING_FUNC = 32 ' ', m_accum_properties = 143 '\217'}

How to repeat:
We set a watchpoint on the example variable and run the program backwards to see when it last changed. From the stack trace below, it appears the last time it was touched it was being deleted, yet somehow it is still being accessed later on in the program and causing a crash:

(rr) watch *0x7fbac5269ac0
Hardware watchpoint 2: *0x7fbac5269ac0

(rr) reverse-continue
Continuing.

Thread 2 hit Hardware watchpoint 2: *0x7fbac5269ac0

Old value = -1886417009
New value = -1840105904
__memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:200
200 ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: No such file or directory.
(rr) bt
#0 __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:200
#1 0x0000559f8d04f38b in TRASH (ptr=0x7fbac5269ac0, length=200) at /github/MySQL/mysql-server/include/memory_debugging.h:72  <--- Function that writes 0x8f repeatedly into the object.

#2 0x0000559f8d073e8e in Item::operator delete (ptr=0x7fbac5269ac0, size=200) at /github/MySQL/mysql-server/sql/item.h:881 <--- delete operator is being called on the object

#3 0x0000559f8d6a6881 in Item_cache_int::~Item_cache_int (this=0x7fbac5269ac0, __in_chrg=<optimized out>) at /github/MySQL/mysql-server/sql/item.h:6788
#4 0x0000559f8d1238de in Item::delete_self (this=0x7fbac5269ac0) at /github/MySQL/mysql-server/sql/item.h:3089
#5 0x0000559f8d11cdbd in Query_arena::free_items (this=0x7fbac4694a78) at /github/MySQL/mysql-server/sql/sql_class.cc:2016
#6 0x0000559f8d11be5e in THD::cleanup_after_query (this=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_class.cc:1804
#7 0x0000559f8d0c76fc in sp_head::execute (this=0x7fbac4795800, thd=0x7fbac4694a70, merge_da_on_success=true) at /github/MySQL/mysql-server/sql/sp_head.cc:2242
#8 0x0000559f8d0c976a in sp_head::execute_procedure (this=0x7fbac4795800, thd=0x7fbac4694a70, args=0x7fbac469f0e0) at /github/MySQL/mysql-server/sql/sp_head.cc:2866
#9 0x0000559f8d9ad53b in Sql_cmd_call::execute_inner (this=0x7fbac469fc98, thd=0x7fbac4694a70) at /github/MySQL/mysql-server/sql/sql_call.cc:235
#10 0x0000559f8d2aacfd in Sql_cmd_dml::execute (this=0x7fbac469fc98, 
...
[16 Apr 16:11] MySQL Verification Team
HI Mr. Othiens,

Thank you for your bug report.

However, we are not able to repeat it, without all tables and the necessary amount of rows, so that crash happens.

We have found MANY possible bugs that are already verified, that could be the original bugs for your report.

However, all of those occur in a SELECT, not in the stored routines, which is why their stacktrace is different. All these reports are security vulnerability bugs, so you can not see them, at all.

So, please, let us know if that SELECT, by itself, crashes a server and what does a full stacktrace look like in that case.

Can't repeat.
[16 Apr 16:52] Nicholas Othieno
A pull request has been submitted for the issue in https://github.com/mysql/mysql-server/pull/537
[17 Apr 0:15] Omer Barnir
Contribution for this bug (https://github.com/mysql/mysql-server/pull/537) logged as bug#114662
[17 Apr 10:13] MySQL Verification Team
Hi ,

Thank you for your contribution.

Your bug has been verified as:

https://bugs.mysql.com/bug.php?id=114662