[Commits] 4625830b679: MDEV-17783: AddressSanitizer: stack-buffer-overflow in table_cond_selectivity

Sergei Petrunia psergey at askmonty.org
Thu May 20 18:23:12 EEST 2021


revision-id: 4625830b6794184a57c2702436e810be941a51c0 (mariadb-10.2.31-960-g4625830b679)
parent(s): af8d4a97e29905f2806e7f26b420ce517e96c723
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2021-05-20 18:23:12 +0300
message:

MDEV-17783: AddressSanitizer: stack-buffer-overflow in table_cond_selectivity

A less-intrusive fix: don't have table_cond_selectivity() assume that
there are less than MAX_REF_PARTS hash-join KEYUSEs.

If there are more than that, switch to using an array. Allocate the array
on the heap: we can't allocate it on MEM_ROOT as table_cond_selectivity()
is called many times during the optimization.

---
 mysql-test/r/selectivity_innodb.result | 29 +++++++++++++++++++++++++++++
 mysql-test/t/selectivity_innodb.test   | 34 ++++++++++++++++++++++++++++++++++
 sql/sql_select.cc                      | 25 ++++++++++++++++++++++++-
 3 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/mysql-test/r/selectivity_innodb.result b/mysql-test/r/selectivity_innodb.result
index 5452919aa6d..23e0fcc9387 100644
--- a/mysql-test/r/selectivity_innodb.result
+++ b/mysql-test/r/selectivity_innodb.result
@@ -2103,6 +2103,35 @@ drop view v1;
 #
 # End of 10.1 tests
 #
+#
+# MDEV-17783: AddressSanitizer: stack-buffer-overflow in table_cond_selectivity
+#
+set
+ at tmp_jcl=@@join_cache_level,
+ at tmp_sel=@@optimizer_use_condition_selectivity;
+set
+join_cache_level=3,
+optimizer_use_condition_selectivity=2;
+CREATE TABLE t1 (
+c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int, c9 int, c10 int,
+c11 int, c12 int, c13 int, c14 int, c15 int, c16 int, c17 int, c18 int, c19 int,
+c20 int, c21 int, c22 int, c23 int, c24 int, c25 int, c26 int, c27 int, c28 int,
+c29 int, c30 int, c31 int, c32 int, c33 int, c34 int
+) ENGINE=InnoDB;
+SELECT * FROM t1
+WHERE
+(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10,
+c11, c12, c13, c14, c15, c16, c17, c18, c19,
+c20, c21, c22, c23, c24, c25, c26, c27, c28, c29,
+c30, c31, c32, c33, c34) IN (SELECT * FROM t1) ;
+c1	c2	c3	c4	c5	c6	c7	c8	c9	c10	c11	c12	c13	c14	c15	c16	c17	c18	c19	c20	c21	c22	c23	c24	c25	c26	c27	c28	c29	c30	c31	c32	c33	c34
+set
+join_cache_level=@tmp_jcl,
+optimizer_use_condition_selectivity=@tmp_sel;
+drop table t1;
+#
+# End of 10.1 tests
+#
 set use_stat_tables= @tmp_ust;
 set optimizer_use_condition_selectivity= @tmp_oucs;
 set @@global.histogram_size=@save_histogram_size;
diff --git a/mysql-test/t/selectivity_innodb.test b/mysql-test/t/selectivity_innodb.test
index 6c457e2848b..eb05091e43a 100644
--- a/mysql-test/t/selectivity_innodb.test
+++ b/mysql-test/t/selectivity_innodb.test
@@ -174,6 +174,40 @@ drop view v1;
 --echo # End of 10.1 tests
 --echo #
 
+--echo #
+--echo # MDEV-17783: AddressSanitizer: stack-buffer-overflow in table_cond_selectivity
+--echo #
+
+set
+  @tmp_jcl=@@join_cache_level,
+  @tmp_sel=@@optimizer_use_condition_selectivity;
+set
+  join_cache_level=3,
+  optimizer_use_condition_selectivity=2;
+
+CREATE TABLE t1 (
+  c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int, c9 int, c10 int,
+  c11 int, c12 int, c13 int, c14 int, c15 int, c16 int, c17 int, c18 int, c19 int,
+  c20 int, c21 int, c22 int, c23 int, c24 int, c25 int, c26 int, c27 int, c28 int,
+  c29 int, c30 int, c31 int, c32 int, c33 int, c34 int
+) ENGINE=InnoDB;
+
+SELECT * FROM t1
+WHERE
+  (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10,
+   c11, c12, c13, c14, c15, c16, c17, c18, c19,
+   c20, c21, c22, c23, c24, c25, c26, c27, c28, c29,
+   c30, c31, c32, c33, c34) IN (SELECT * FROM t1) ;
+
+set
+  join_cache_level=@tmp_jcl,
+  optimizer_use_condition_selectivity=@tmp_sel;
+drop table t1;
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
+
 set use_stat_tables= @tmp_ust;
 set optimizer_use_condition_selectivity= @tmp_oucs;
 set @@global.histogram_size=@save_histogram_size;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ce706209017..950d8f8fa70 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7949,7 +7949,9 @@ static
 double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
                               table_map rem_tables)
 {
-  uint16 ref_keyuse_steps[MAX_REF_PARTS - 1];
+  uint16 ref_keyuse_steps_buf[MAX_REF_PARTS - 1];
+  uint   ref_keyuse_size= MAX_REF_PARTS - 1;
+  uint16 *ref_keyuse_steps= ref_keyuse_steps_buf;
   Field *field;
   TABLE *table= s->table;
   MY_BITMAP *read_set= table->read_set;
@@ -8096,6 +8098,24 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
             }
             if (keyparts > 1)
 	    {
+              if (keyparts - 2 >= ref_keyuse_size)
+              {
+                uint new_size= MY_MAX(ref_keyuse_size*2, keyparts);
+                void *new_buf;
+                if (!(new_buf= my_malloc(sizeof(uint16)*new_size, MYF(0))))
+                {
+                  if (ref_keyuse_steps != ref_keyuse_steps_buf)
+                    my_free(ref_keyuse_steps);
+                  return 1.0; // As if no selectivity was computed
+                }
+                memcpy(new_buf, ref_keyuse_steps,
+                       sizeof(uint16)*ref_keyuse_size);
+                if (ref_keyuse_steps != ref_keyuse_steps_buf)
+                  my_free(ref_keyuse_steps);
+
+                ref_keyuse_steps= (uint16*)new_buf;
+                ref_keyuse_size= new_size;
+              }
               ref_keyuse_steps[keyparts-2]= (uint16)(keyuse - prev_ref_keyuse);
               prev_ref_keyuse= keyuse;
             }
@@ -8151,6 +8171,9 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
   sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables,
                                         keyparts, ref_keyuse_steps);
 
+  if (ref_keyuse_steps != ref_keyuse_steps_buf)
+    my_free(ref_keyuse_steps);
+
   return sel;
 }
 


More information about the commits mailing list