List:Commits« Previous MessageNext Message »
From:Sergey Glukhov Date:April 14 2011 9:33am
Subject:bzr push into mysql-5.1 branch (sergey.glukhov:3657 to 3658) Bug#11756242
View as plain text  
 3658 Sergey Glukhov	2011-04-14
      Bug#11756242  48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
      There are two problems with ANALYSE():
      
      1. Memory leak 
         it happens because do_select() can overwrite
         JOIN::procedure field(with zero value in our case) and
         JOIN destructor don't free the memory allocated for
         JOIN::procedure. The fix is to save original JOIN::procedure
         before do_select() call and restore it after do_select
         execution.
      
      2. Wrong result
         If ANALYSE() procedure is used for the statement with LIMIT clause
         it could retrun empty result set. It happens because of missing 
         analyse::end_of_records() call. First end_send() function call
         returns NESTED_LOOP_QUERY_LIMIT and second call of end_send() with
         end_of_records flag enabled does not happen. The fix is to return
         NESTED_LOOP_OK from end_send() if procedure is active.
     @ mysql-test/r/analyse.result
        test case
     @ mysql-test/t/analyse.test
        test case
     @ sql/sql_select.cc
        --save original JOIN::procedure before do_select() call and
          restore it after do_select execution.
        --return NESTED_LOOP_OK from end_send() if procedure is active

    modified:
      mysql-test/r/analyse.result
      mysql-test/t/analyse.test
      sql/sql_select.cc
 3657 Serge Kozlov	2011-04-14
      WL#5867, reorganize test cases of bugs suite

    removed:
      mysql-test/suite/bugs/
      mysql-test/suite/bugs/combinations
      mysql-test/suite/bugs/data/
      mysql-test/suite/bugs/data/rpl_bug12691.dat
      mysql-test/suite/bugs/r/
      mysql-test/suite/bugs/r/rpl_bug12691.result
      mysql-test/suite/bugs/r/rpl_bug31582.result
      mysql-test/suite/bugs/r/rpl_bug31583.result
      mysql-test/suite/bugs/r/rpl_bug33029.result
      mysql-test/suite/bugs/r/rpl_bug38205.result
      mysql-test/suite/bugs/t/
      mysql-test/suite/bugs/t/rpl_bug12691.test
      mysql-test/suite/bugs/t/rpl_bug31582.test
      mysql-test/suite/bugs/t/rpl_bug31583.test
      mysql-test/suite/bugs/t/rpl_bug33029.test
      mysql-test/suite/bugs/t/rpl_bug38205.test
    renamed:
      mysql-test/suite/bugs/r/rpl_bug23533.result => mysql-test/suite/binlog/r/binlog_bug23533.result
      mysql-test/suite/bugs/r/rpl_bug36391.result => mysql-test/suite/binlog/r/binlog_bug36391.result
      mysql-test/suite/bugs/r/rpl_bug37426.result => mysql-test/suite/rpl/r/rpl_bug37426.result
      mysql-test/suite/bugs/t/rpl_bug23533.test => mysql-test/suite/binlog/t/binlog_bug23533.test
      mysql-test/suite/bugs/t/rpl_bug36391-master.opt => mysql-test/suite/binlog/t/binlog_bug36391-master.opt
      mysql-test/suite/bugs/t/rpl_bug36391.test => mysql-test/suite/binlog/t/binlog_bug36391.test
      mysql-test/suite/bugs/t/rpl_bug37426.test => mysql-test/suite/rpl/t/rpl_bug37426.test
    modified:
      mysql-test/collections/default.experimental
      mysql-test/suite/binlog/r/binlog_bug23533.result
      mysql-test/suite/binlog/r/binlog_bug36391.result
      mysql-test/suite/rpl/r/rpl_bug37426.result
      mysql-test/suite/binlog/t/binlog_bug23533.test
      mysql-test/suite/binlog/t/binlog_bug36391.test
      mysql-test/suite/rpl/t/rpl_bug37426.test
=== modified file 'mysql-test/r/analyse.result'
--- a/mysql-test/r/analyse.result	2011-03-14 18:03:22 +0000
+++ b/mysql-test/r/analyse.result	2011-04-14 08:11:57 +0000
@@ -135,4 +135,17 @@ SELECT * FROM t1 PROCEDURE ANALYSE();
 Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
 test.t1.a	e	e-	1	2	0	0	1.3333	NULL	ENUM('e','e-') NOT NULL
 DROP TABLE t1;
+#
+# Bug#11756242  48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
+#
+CREATE TABLE t1(f1 INT) ENGINE=MYISAM;
+CREATE TABLE t2(f2 INT) ENGINE=INNODB;
+INSERT INTO t2 VALUES (1);
+SELECT DISTINCTROW f1 FROM t1 NATURAL RIGHT OUTER JOIN t2 PROCEDURE ANALYSE();
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+test.t1.f1	NULL	NULL	0	0	0	1	0.0	0.0	CHAR(0)
+SELECT * FROM t2 LIMIT 1 PROCEDURE ANALYSE();
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+test.t2.f2	1	1	1	1	0	0	1.0000	0.0000	ENUM('1') NOT NULL
+DROP TABLE t1, t2;
 End of 5.1 tests

=== modified file 'mysql-test/t/analyse.test'
--- a/mysql-test/t/analyse.test	2011-03-14 18:03:22 +0000
+++ b/mysql-test/t/analyse.test	2011-04-14 08:11:57 +0000
@@ -1,6 +1,7 @@
 #
 # Test of procedure analyse
 #
+-- source include/have_innodb.inc
 
 --disable_warnings
 drop table if exists t1,t2;
@@ -144,4 +145,15 @@ INSERT INTO t1 VALUES ('e'),('e'),('e-')
 SELECT * FROM t1 PROCEDURE ANALYSE();
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#11756242  48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
+--echo #
+
+CREATE TABLE t1(f1 INT) ENGINE=MYISAM;
+CREATE TABLE t2(f2 INT) ENGINE=INNODB;
+INSERT INTO t2 VALUES (1);
+SELECT DISTINCTROW f1 FROM t1 NATURAL RIGHT OUTER JOIN t2 PROCEDURE ANALYSE();
+SELECT * FROM t2 LIMIT 1 PROCEDURE ANALYSE();
+DROP TABLE t1, t2;
+
 --echo End of 5.1 tests

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-02-22 21:03:32 +0000
+++ b/sql/sql_select.cc	2011-04-14 08:11:57 +0000
@@ -1929,7 +1929,11 @@ JOIN::exec()
     if (!curr_join->sort_and_group &&
         curr_join->const_tables != curr_join->tables)
       curr_join->join_tab[curr_join->const_tables].sorted= 0;
-    if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
+
+    Procedure *save_proc= curr_join->procedure;
+    tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0);
+    curr_join->procedure= save_proc;
+    if (tmp_error)
     {
       error= tmp_error;
       DBUG_VOID_RETURN;
@@ -12354,10 +12358,14 @@ end_send(JOIN *join, JOIN_TAB *join_tab 
     int error;
     if (join->having && join->having->val_int() == 0)
       DBUG_RETURN(NESTED_LOOP_OK);               // Didn't match having
-    error=0;
     if (join->procedure)
-      error=join->procedure->send_row(join->procedure_fields_list);
-    else if (join->do_send_rows)
+    {
+      if (join->procedure->send_row(join->procedure_fields_list))
+        DBUG_RETURN(NESTED_LOOP_ERROR);
+      DBUG_RETURN(NESTED_LOOP_OK);
+    }
+    error=0;
+    if (join->do_send_rows)
       error=join->result->send_data(*join->fields);
     if (error)
       DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1 branch (sergey.glukhov:3657 to 3658) Bug#11756242Sergey Glukhov14 Apr