From 73f415c955df91f231e37ce2bc062f06f1490602 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Tue, 21 Jan 2025 12:26:51 +0700 Subject: [PATCH] MDEV-24935: Server crashes in Field_iterator_natural_join::next or Field_iterator_table_ref::set_field_iterator upon 2nd execution of SP Calling a stored routine that executes a join on three or more tables and referencing not-existent column name in the USING clause resulted in a crash on its second invocation. Server crash taken place by the reason of dereferencing null pointer in condition of DBUG_ASSERT inside the method Field_iterator_natural_join::next() There the data member cur_column_ref->table_field->field has the nullptr value that was reset at the end of first execution of a stored routine when the standalone procedure cleanup_items() called by the method sp_head::execute. Later this data member is not re-initialized and never referenced in any place except the DBUG_ASSERT on second and later invocations of the stored routine. To fix the issue, the assert's condition should be augmented by a condition '|| !cur_column_ref->table_field' before dereferencing cur_column_ref->table_field. Such extra checking is aligned with conditions used by DBUG_ASSERT macros used by implementation of the class Field_iterator_table_ref that aggregated the class Field_iterator_natural_join. --- mysql-test/main/sp-bugs.result | 27 +++++++++++++++++++++++++++ mysql-test/main/sp-bugs.test | 31 +++++++++++++++++++++++++++++++ sql/table.cc | 1 + 3 files changed, 59 insertions(+) diff --git a/mysql-test/main/sp-bugs.result b/mysql-test/main/sp-bugs.result index a166a5a0a9a..bd5883f0a04 100644 --- a/mysql-test/main/sp-bugs.result +++ b/mysql-test/main/sp-bugs.result @@ -363,3 +363,30 @@ ERROR HY000: Unknown thread id: 0 # # End of 10.4 tests # +# +# MDEV-24935: Server crashes in Field_iterator_natural_join::next or Field_iterator_table_ref::set_field_iterator upon 2nd execution of SP +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, c INT); +CREATE TABLE t3 (d INT); +CREATE PROCEDURE sp() SELECT * FROM t1 JOIN t2 JOIN t3 USING (x); +CALL sp; +ERROR 42S22: Unknown column 'x' in 'from clause' +CALL sp; +ERROR 42S22: Unknown column 'x' in 'from clause' +# Clean up +DROP PROCEDURE sp; +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (c1 INT,c2 INT); +CREATE TABLE t2 (c INT,c2 INT); +CREATE PROCEDURE p2 (OUT i INT,OUT o INT) READS SQL DATA DELETE a2,a3 FROM t1 AS a1 JOIN t2 AS a2 NATURAL JOIN t2 AS a3; +CALL p2 (@c,@a); +ERROR 23000: Column 'c2' in from clause is ambiguous +CALL p2 (@a,@c); +ERROR 23000: Column 'c2' in from clause is ambiguous +# Clean up +DROP PROCEDURE p2; +DROP TABLE t1, t2; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/sp-bugs.test b/mysql-test/main/sp-bugs.test index 18fe14dc8bc..f44216fbf46 100644 --- a/mysql-test/main/sp-bugs.test +++ b/mysql-test/main/sp-bugs.test @@ -386,3 +386,34 @@ KILL (('x' IN ( SELECT 1)) MOD 44); --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # MDEV-24935: Server crashes in Field_iterator_natural_join::next or Field_iterator_table_ref::set_field_iterator upon 2nd execution of SP +--echo # +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, c INT); +CREATE TABLE t3 (d INT); +CREATE PROCEDURE sp() SELECT * FROM t1 JOIN t2 JOIN t3 USING (x); +--error ER_BAD_FIELD_ERROR +CALL sp; +--error ER_BAD_FIELD_ERROR +CALL sp; +--echo # Clean up +DROP PROCEDURE sp; +DROP TABLE t1, t2, t3; + +CREATE TABLE t1 (c1 INT,c2 INT); +CREATE TABLE t2 (c INT,c2 INT); +CREATE PROCEDURE p2 (OUT i INT,OUT o INT) READS SQL DATA DELETE a2,a3 FROM t1 AS a1 JOIN t2 AS a2 NATURAL JOIN t2 AS a3; + +--error ER_NON_UNIQ_ERROR +CALL p2 (@c,@a); +--error ER_NON_UNIQ_ERROR +CALL p2 (@a,@c); +--echo # Clean up +DROP PROCEDURE p2; +DROP TABLE t1, t2; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/table.cc b/sql/table.cc index 0aad7ae24e1..978dbee254e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6948,6 +6948,7 @@ void Field_iterator_natural_join::next() { cur_column_ref= column_ref_it++; DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || + !cur_column_ref->table_field->field || cur_column_ref->table_ref->table == cur_column_ref->table_field->field->table); }