[Commits] 54bcbc3: DEV-8632 Segmentation fault on INSERT

sanja at mariadb.com sanja at mariadb.com
Mon Nov 9 17:06:07 EET 2015


revision-id: 54bcbc3777830e2599b77de17fc28b2ccdadd081 (mariadb-5.5.46-3-g54bcbc3)
parent(s): df804208657dfae10e24d656d9228f05e57b14a5
committer: Oleksandr Byelkin
timestamp: 2015-11-09 16:06:05 +0100
message:

DEV-8632 Segmentation fault on INSERT

View/derived fields should be taken into account when we build ref_pointer_array constructed.

DBUG_ASSERTs added to avoid memory overrun.

---
 mysql-test/r/view.result | 33 +++++++++++++++++++++++++++++++++
 mysql-test/t/view.test   | 35 +++++++++++++++++++++++++++++++++++
 sql/item.cc              |  3 +++
 sql/sql_select.cc        |  6 ++++++
 sql/sql_view.cc          |  5 +++++
 sql/sql_yacc.yy          |  9 +++++++++
 6 files changed, 91 insertions(+)

diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 57065d7..b008e62 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -5479,6 +5479,39 @@ UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 );
 EXECUTE stmt;
 DROP TABLE t1, t2, t3;
 DROP VIEW v3;
+#
+# MDEV-8632: Segmentation fault on INSERT
+#
+CREATE TABLE `t1` (
+`id` int(10) unsigned NOT NULL,
+`r` float NOT NULL,
+PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+create view v1 as select id, if(r=r,1,2) as d from t1;
+create view v2 as
+select id, 
+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+from v1;
+insert into t1 (id, r)
+select id,p from
+(
+select id, 
+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+from (
+select id, if(r=r,1,2) as d
+from t1
+) a
+) b
+on duplicate key update r=p;
+insert into t1 (id, r)
+select id,p from v2 
+on duplicate key update r=p;
+prepare stmt from "insert into t1 (id, r) select id,p from v2 on duplicate key update r=p";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+drop view v1,v2;
+drop table `t1`;
 # -----------------------------------------------------------------
 # -- End of 5.5 tests.
 # -----------------------------------------------------------------
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index fe04cdf..815be87 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -5445,6 +5445,41 @@ EXECUTE stmt;
 DROP TABLE t1, t2, t3;
 DROP VIEW v3;
 
+--echo #
+--echo # MDEV-8632: Segmentation fault on INSERT
+--echo #
+CREATE TABLE `t1` (
+  `id` int(10) unsigned NOT NULL,
+  `r` float NOT NULL,
+  PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+create view v1 as select id, if(r=r,1,2) as d from t1;
+create view v2 as
+  select id, 
+  d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+  from v1;
+insert into t1 (id, r)
+select id,p from
+(
+  select id, 
+  d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+  from (
+    select id, if(r=r,1,2) as d
+    from t1
+  ) a
+) b
+on duplicate key update r=p;
+insert into t1 (id, r)
+select id,p from v2 
+on duplicate key update r=p;
+
+prepare stmt from "insert into t1 (id, r) select id,p from v2 on duplicate key update r=p";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
+drop view v1,v2;
+drop table `t1`;
 --echo # -----------------------------------------------------------------
 --echo # -- End of 5.5 tests.
 --echo # -----------------------------------------------------------------
diff --git a/sql/item.cc b/sql/item.cc
index 878c960..840272c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1891,6 +1891,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
     */
     Item_aggregate_ref *item_ref;
     uint el= fields.elements;
+    DBUG_ASSERT(fields.elements <=
+                thd->lex->current_select->ref_pointer_array_size);
     /*
       If this is an item_ref, get the original item
       This is a safety measure if this is called for things that is
@@ -6719,6 +6721,7 @@ Item *Item_field::update_value_transformer(uchar *select_arg)
   {
     List<Item> *all_fields= &select->join->all_fields;
     Item **ref_pointer_array= select->ref_pointer_array;
+    DBUG_ASSERT(all_fields->elements <= select->ref_pointer_array_size);
     int el= all_fields->elements;
     Item_ref *ref;
 
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e960a3d..ef1b5b0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -427,6 +427,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
     if (ref_pointer_array && !ref->found_in_select_list)
     {
       int el= all_fields.elements;
+      DBUG_ASSERT(all_fields.elements <= select->ref_pointer_array_size);
       ref_pointer_array[el]= item;
       /* Add the field item to the select list of the current select. */
       all_fields.push_front(item);
@@ -832,6 +833,7 @@ JOIN::prepare(Item ***rref_pointer_array,
       {
         Item_field *field= new Item_field(thd, *(Item_field**)ord->item);
         int el= all_fields.elements;
+        DBUG_ASSERT(all_fields.elements <= select_lex->ref_pointer_array_size);
         ref_pointer_array[el]= field;
         all_fields.push_front(field);
         ord->item= ref_pointer_array + el;
@@ -20596,6 +20598,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
     return TRUE; /* Wrong field. */
 
   uint el= all_fields.elements;
+  DBUG_ASSERT(all_fields.elements <=
+              thd->lex->current_select->ref_pointer_array_size);
   all_fields.push_front(order_item); /* Add new field to field list. */
   ref_pointer_array[el]= order_item;
   /*
@@ -20855,6 +20859,8 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
         */
         Item_field *new_item= new Item_field(thd, (Item_field*)item);
         int el= all_fields.elements;
+        DBUG_ASSERT(all_fields.elements <=
+                    thd->lex->current_select->ref_pointer_array_size);
         orig_ref_pointer_array[el]= new_item;
         all_fields.push_front(new_item);
         ord->item= orig_ref_pointer_array + el;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 255f876..e6c5ffd 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1520,6 +1520,11 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
       */
       lex->sql_command= old_lex->sql_command;
       lex->duplicates= old_lex->duplicates;
+
+      /* Fields in this view can be used in upper select in case of merge.  */
+      if (table->select_lex)
+        table->select_lex->select_n_where_fields+=
+          lex->select_lex.select_n_where_fields;
     }
     /*
       This method has a dependency on the proper lock type being set,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a49dea6..11d7efd 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -9872,6 +9872,15 @@ table_factor:
               sel->add_joined_table($$);
               lex->pop_context();
               lex->nest_level--;
+              /*
+                Fields in derived table can be used in upper select in
+                case of merge. We do not add HAVING fields because we do
+                not merge such derived. We do not add union because
+                also do not merge them
+              */
+              if (!sel->next_select())
+                $2->select_n_where_fields+=
+                  sel->select_n_where_fields;
             }
             /*else if (($3->select_lex &&
                       $3->select_lex->master_unit()->is_union() &&


More information about the commits mailing list