|
| 1 | +From a9b6bf9fa83604ac13e921c150a2806a64d23f92 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Mayank Singh <mayansingh@microsoft.com> |
| 3 | +Date: Mon, 5 May 2025 09:20:46 +0000 |
| 4 | +Subject: [PATCH] Address CVE-2023-52971 |
| 5 | +Upstream Reference Link: https://github.com/MariaDB/server/commit/3b4de4c281cb3e33e6d3ee9537e542bf0a84b83e |
| 6 | + |
| 7 | +--- |
| 8 | + mysql-test/main/join_nested.result | 12 +++++ |
| 9 | + mysql-test/main/join_nested.test | 13 ++++++ |
| 10 | + mysql-test/main/join_nested_jcl6.result | 12 +++++ |
| 11 | + sql/sql_select.cc | 58 +++++++++++++++++++++++-- |
| 12 | + 4 files changed, 91 insertions(+), 4 deletions(-) |
| 13 | + |
| 14 | +diff --git a/mysql-test/main/join_nested.result b/mysql-test/main/join_nested.result |
| 15 | +index cb9dffc8..56468518 100644 |
| 16 | +--- a/mysql-test/main/join_nested.result |
| 17 | ++++ b/mysql-test/main/join_nested.result |
| 18 | +@@ -2051,3 +2051,15 @@ a b c a a b |
| 19 | + DROP TABLE t1, t2, t3; |
| 20 | + set join_cache_level= @save_join_cache_level; |
| 21 | + # end of 10.3 tests |
| 22 | ++# |
| 23 | ++# MDEV-32084: Assertion in best_extension_by_limited_search(), or crash elsewhere in release |
| 24 | ++# |
| 25 | ++CREATE TABLE t1 (i int); |
| 26 | ++INSERT INTO t1 values (1),(2); |
| 27 | ++SELECT 1 FROM t1 WHERE i IN |
| 28 | ++(SELECT 1 FROM t1 c |
| 29 | ++LEFT JOIN (t1 a LEFT JOIN t1 b ON t1.i = b.i) ON c.i = t1.i); |
| 30 | ++1 |
| 31 | ++1 |
| 32 | ++DROP TABLE t1; |
| 33 | ++# end of 10.11 tests |
| 34 | +diff --git a/mysql-test/main/join_nested.test b/mysql-test/main/join_nested.test |
| 35 | +index ed1fe4c9..62370b95 100644 |
| 36 | +--- a/mysql-test/main/join_nested.test |
| 37 | ++++ b/mysql-test/main/join_nested.test |
| 38 | +@@ -1458,3 +1458,16 @@ DROP TABLE t1, t2, t3; |
| 39 | + set join_cache_level= @save_join_cache_level; |
| 40 | + |
| 41 | + --echo # end of 10.3 tests |
| 42 | ++ |
| 43 | ++--echo # |
| 44 | ++--echo # MDEV-32084: Assertion in best_extension_by_limited_search(), or crash elsewhere in release |
| 45 | ++--echo # |
| 46 | ++CREATE TABLE t1 (i int); |
| 47 | ++INSERT INTO t1 values (1),(2); |
| 48 | ++ |
| 49 | ++SELECT 1 FROM t1 WHERE i IN |
| 50 | ++ (SELECT 1 FROM t1 c |
| 51 | ++ LEFT JOIN (t1 a LEFT JOIN t1 b ON t1.i = b.i) ON c.i = t1.i); |
| 52 | ++ |
| 53 | ++DROP TABLE t1; |
| 54 | ++--echo # end of 10.11 tests |
| 55 | +diff --git a/mysql-test/main/join_nested_jcl6.result b/mysql-test/main/join_nested_jcl6.result |
| 56 | +index 0bda8d43..50a1e83a 100644 |
| 57 | +--- a/mysql-test/main/join_nested_jcl6.result |
| 58 | ++++ b/mysql-test/main/join_nested_jcl6.result |
| 59 | +@@ -2060,6 +2060,18 @@ a b c a a b |
| 60 | + DROP TABLE t1, t2, t3; |
| 61 | + set join_cache_level= @save_join_cache_level; |
| 62 | + # end of 10.3 tests |
| 63 | ++# |
| 64 | ++# MDEV-32084: Assertion in best_extension_by_limited_search(), or crash elsewhere in release |
| 65 | ++# |
| 66 | ++CREATE TABLE t1 (i int); |
| 67 | ++INSERT INTO t1 values (1),(2); |
| 68 | ++SELECT 1 FROM t1 WHERE i IN |
| 69 | ++(SELECT 1 FROM t1 c |
| 70 | ++LEFT JOIN (t1 a LEFT JOIN t1 b ON t1.i = b.i) ON c.i = t1.i); |
| 71 | ++1 |
| 72 | ++1 |
| 73 | ++DROP TABLE t1; |
| 74 | ++# end of 10.11 tests |
| 75 | + CREATE TABLE t5 (a int, b int, c int, PRIMARY KEY(a), KEY b_i (b)); |
| 76 | + CREATE TABLE t6 (a int, b int, c int, PRIMARY KEY(a), KEY b_i (b)); |
| 77 | + CREATE TABLE t7 (a int, b int, c int, PRIMARY KEY(a), KEY b_i (b)); |
| 78 | +diff --git a/sql/sql_select.cc b/sql/sql_select.cc |
| 79 | +index b88e8b4c..b8e15264 100644 |
| 80 | +--- a/sql/sql_select.cc |
| 81 | ++++ b/sql/sql_select.cc |
| 82 | +@@ -18544,6 +18544,8 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, |
| 83 | + prev_table->dep_tables|= used_tables; |
| 84 | + if (prev_table->on_expr) |
| 85 | + { |
| 86 | ++ /* If the ON expression is still there, it's an outer join */ |
| 87 | ++ DBUG_ASSERT(prev_table->outer_join); |
| 88 | + prev_table->dep_tables|= table->on_expr_dep_tables; |
| 89 | + table_map prev_used_tables= prev_table->nested_join ? |
| 90 | + prev_table->nested_join->used_tables : |
| 91 | +@@ -18558,11 +18560,59 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, |
| 92 | + prevents update of inner table dependences. |
| 93 | + For example it might happen if RAND() function |
| 94 | + is used in JOIN ON clause. |
| 95 | +- */ |
| 96 | +- if (!((prev_table->on_expr->used_tables() & |
| 97 | +- ~(OUTER_REF_TABLE_BIT | RAND_TABLE_BIT)) & |
| 98 | +- ~prev_used_tables)) |
| 99 | ++ */ |
| 100 | ++ table_map prev_on_expr_deps= prev_table->on_expr->used_tables() & |
| 101 | ++ ~(OUTER_REF_TABLE_BIT | RAND_TABLE_BIT); |
| 102 | ++ prev_on_expr_deps&= ~prev_used_tables; |
| 103 | ++ |
| 104 | ++ if (!prev_on_expr_deps) |
| 105 | + prev_table->dep_tables|= used_tables; |
| 106 | ++ else |
| 107 | ++ { |
| 108 | ++ /* |
| 109 | ++ Another possible case is when prev_on_expr_deps!=0 but it depends |
| 110 | ++ on a table outside this join nest. SQL name resolution don't allow |
| 111 | ++ this but it is possible when LEFT JOIN is inside a subquery which |
| 112 | ++ is converted into a semi-join nest, Example: |
| 113 | ++ |
| 114 | ++ t1 SEMI JOIN ( |
| 115 | ++ t2 |
| 116 | ++ LEFT JOIN (t3 LEFT JOIN t4 ON t4.col=t1.col) ON expr |
| 117 | ++ ) ON ... |
| 118 | ++ |
| 119 | ++ here, we would have prev_table=t4, table=t3. The condition |
| 120 | ++ "ON t4.col=t1.col" depends on tables {t1, t4}. To make sure the |
| 121 | ++ optimizer puts t3 before t4 we need to make sure t4.dep_tables |
| 122 | ++ includes t3. |
| 123 | ++ */ |
| 124 | ++ |
| 125 | ++ DBUG_ASSERT(table->embedding == prev_table->embedding); |
| 126 | ++ if (table->embedding) |
| 127 | ++ { |
| 128 | ++ /* |
| 129 | ++ Find what are the "peers" of "table" in the join nest. Normally, |
| 130 | ++ it is table->embedding->nested_join->used_tables, but here we are |
| 131 | ++ in the process of recomputing that value. |
| 132 | ++ So, we walk the join list and collect the bitmap of peers: |
| 133 | ++ */ |
| 134 | ++ table_map peers= 0; |
| 135 | ++ List_iterator_fast<TABLE_LIST> li(*join_list); |
| 136 | ++ TABLE_LIST *peer; |
| 137 | ++ while ((peer= li++)) |
| 138 | ++ { |
| 139 | ++ table_map curmap= peer->nested_join |
| 140 | ++ ? peer->nested_join->used_tables |
| 141 | ++ : peer->get_map(); |
| 142 | ++ peers|= curmap; |
| 143 | ++ } |
| 144 | ++ /* |
| 145 | ++ If prev_table doesn't depend on any of its peers, add a |
| 146 | ++ dependency on nearest peer, that is, on 'table'. |
| 147 | ++ */ |
| 148 | ++ if (!(prev_on_expr_deps & peers)) |
| 149 | ++ prev_table->dep_tables|= used_tables; |
| 150 | ++ } |
| 151 | ++ } |
| 152 | + } |
| 153 | + } |
| 154 | + prev_table= table; |
| 155 | +-- |
| 156 | +2.45.3 |
| 157 | + |
0 commit comments