From caebe151c18a3415466cca88dbdacb8ec9597a29 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Thu, 7 Oct 2021 17:02:26 +0300 Subject: [PATCH] MDEV-22445 Crash on HANDLER READ NEXT after XA PREPARE The assertion is absolutely correct since no data access is possible after XA PREPARE. The check is added in mysql_ha_read. --- mysql-test/r/xa.result | 15 +++++++++++++++ mysql-test/t/xa.test | 17 +++++++++++++++++ sql/sql_handler.cc | 3 +++ 3 files changed, 35 insertions(+) diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result index 4e4d7bc6048..f6bae2adac2 100644 --- a/mysql-test/r/xa.result +++ b/mysql-test/r/xa.result @@ -341,5 +341,20 @@ Message XAER_RMFAIL: The command cannot be executed when global transaction is i xa commit 'foo'; drop table t1; # +# MDEV-22445 Crash on HANDLER READ NEXT after XA PREPARE +# +CREATE TABLE t (a INT KEY) ENGINE=InnoDB; +HANDLER t OPEN AS t; +XA START '0'; +SELECT * FROM t; +a +XA END '0'; +XA PREPARE '0'; +HANDLER t READ NEXT; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state +# Cleanup +XA COMMIT '0'; +DROP TABLE t; +# # End of 10.2 tests # diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test index b13d12d2019..176b8c3189b 100644 --- a/mysql-test/t/xa.test +++ b/mysql-test/t/xa.test @@ -485,6 +485,23 @@ show status like 'foo'; xa commit 'foo'; drop table t1; +--echo # +--echo # MDEV-22445 Crash on HANDLER READ NEXT after XA PREPARE +--echo # + +CREATE TABLE t (a INT KEY) ENGINE=InnoDB; +HANDLER t OPEN AS t; +XA START '0'; +SELECT * FROM t; +XA END '0'; +XA PREPARE '0'; +--error ER_XAER_RMFAIL +HANDLER t READ NEXT; + +--echo # Cleanup +XA COMMIT '0'; +DROP TABLE t; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 7c2122b6a0a..ec3756eceba 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -697,6 +697,9 @@ retry: if (!(handler= mysql_ha_find_handler(thd, tables->alias))) goto err0; + if (thd->transaction.xid_state.check_has_uncommitted_xa()) + goto err0; + table= handler->table; tables->table= table; // This is used by fix_fields table->pos_in_table_list= tables;