List:Commits« Previous MessageNext Message »
From:Olav Sandstaa Date:August 3 2011 7:22am
Subject:bzr push into mysql-trunk branch (olav.sandstaa:3337 to 3338) Bug#12601961
View as plain text  
 3338 Olav Sandstaa	2011-08-03
      Fix for Bug#12601961 SEGFAULT IN HANDLER::COMPARE_KEY2.
      
      The crash in InnoDB's ICP implementation occured due to the
      handler's end_range member variable having an invalid value.
      As part of the ICP evaluation in InnoDB the code will check
      that the record is within the end_range of the query. In the
      case where this leads to a crash the end_range was not 
      initialized and the code could then reference a non-valid
      memory area leading to the segmentation fault (it could probably
      also lead to a wrong result if the "random end_range" decided
      that the actual record was outside the valid record range).
      
      The case where ICP can be used without having a proper
      end_range defined is for "const" queries that will at most
      access one record. In the case where this occurs the
      table is read from join_read_const() (in sql_select.cc) which
      retrieves data using handler::ha_index_read_idx_map(). 
      Since only max one record will be read, ha_index_read_idx_map()
      does not define an end_range for the handler. In this case
      end_range might be undefined when a pushed index condition
      is evaluated. 
      
      The fix for this problem is to intialized end_range in the
      handler's constructor. The patch also adds an assert to
      ha_index_read_idx_map() to detect if it ever is called
      with an end_range value different from NULL.
      
      Without this fix the test case will either crash or pass
      depending on the value the unitialized end_range get. Running
      with valgrind it should produce a test failure.
     @ mysql-test/include/icp_tests.inc
        Test case for Bug#12601961 SEGFAULT IN HANDLER::COMPARE_KEY2.
     @ mysql-test/r/innodb_icp.result
        Test case for Bug#12601961 SEGFAULT IN HANDLER::COMPARE_KEY2.
     @ mysql-test/r/innodb_icp_none.result
        Test case for Bug#12601961 SEGFAULT IN HANDLER::COMPARE_KEY2.
     @ mysql-test/r/myisam_icp.result
        Test case for Bug#12601961 SEGFAULT IN HANDLER::COMPARE_KEY2.
        Note that this test is not run with MyISAM since it
        triggers a bug in MyISAM. It will be enabled when Bug#12724899
        is fixed.
     @ mysql-test/r/myisam_icp_none.result
        Test case for Bug#12601961 SEGFAULT IN HANDLER::COMPARE_KEY2.
        Note that this test is not run with MyISAM since it
        triggers a bug in MyISAM. It will be enabled when Bug#12724899
        is fixed.
     @ sql/handler.cc
        Add an assert to verify that when handler::ha_index_read_idx_map() is 
        called an end_range is not set. The reason for checking this is that
        this could trigger an invalid end_range verification in the ICP
        implementation.
     @ sql/handler.h
        Initialize the handler's end_range member in the constructor in
        order to avoid that end_range containing a random value is checked
        and results in crash in the ICP implementation in InnoDB.
        
        Also extended the documentation of end_range and save_end_range and
        made save_end_range a protected member of the handler class.

    modified:
      mysql-test/include/icp_tests.inc
      mysql-test/r/innodb_icp.result
      mysql-test/r/innodb_icp_none.result
      mysql-test/r/myisam_icp.result
      mysql-test/r/myisam_icp_none.result
      sql/handler.cc
      sql/handler.h
 3337 Marc Alff	2011-08-03
      Bug#11766111 - 59150: PERFSCHEMA.SETUP_OBJECTS FAILS SPORADICALLY
      
      Post merge cleanup:
      - improved test robustness (better isolation from previous test runs)
      - only update PFS_table_share flags of real records.

    modified:
      mysql-test/suite/perfschema/r/setup_objects.result
      mysql-test/suite/perfschema/t/setup_objects.test
      storage/perfschema/pfs_instr_class.cc
=== modified file 'mysql-test/include/icp_tests.inc'

=== modified file 'mysql-test/include/icp_tests.inc'
--- a/mysql-test/include/icp_tests.inc	2011-06-09 06:22:39 +0000
+++ b/mysql-test/include/icp_tests.inc	2011-08-03 07:21:17 +0000
@@ -964,3 +964,39 @@
 
 DROP VIEW v1;
 DROP TABLE t1;
+
+--echo #
+--echo # BUG#12601961 "SEGFAULT IN HANDLER::COMPARE_KEY2"
+--echo #
+
+# Note: Until Bug#12724899 is fixed this test should only run
+# with InnoDB as storage engine since the query produces
+# wrong result when using MyISAM.
+
+let $se= `select @@default_storage_engine`;
+
+if ($se == 'InnoDB' )
+{
+
+CREATE TABLE t1 (
+  pk INTEGER NOT NULL, 
+  i1 INTEGER NOT NULL,
+  c1 VARCHAR(1) NOT NULL,
+  PRIMARY KEY (pk)
+);
+
+INSERT INTO t1 VALUES (1,3,'j'), (20,8,'e');
+
+let query=
+SELECT alias2.i1
+FROM t1 AS alias1 STRAIGHT_JOIN t1 AS alias2
+ON alias2.pk AND alias2.pk <= alias1.c1
+WHERE alias2.pk = 1;
+
+eval EXPLAIN $query;
+eval $query;
+
+DROP TABLE t1;
+
+}
+

=== modified file 'mysql-test/r/innodb_icp.result'
--- a/mysql-test/r/innodb_icp.result	2011-06-09 06:22:39 +0000
+++ b/mysql-test/r/innodb_icp.result	2011-08-03 07:21:17 +0000
@@ -912,5 +912,30 @@
 pk
 DROP VIEW v1;
 DROP TABLE t1;
+#
+# BUG#12601961 "SEGFAULT IN HANDLER::COMPARE_KEY2"
+#
+CREATE TABLE t1 (
+pk INTEGER NOT NULL, 
+i1 INTEGER NOT NULL,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t1 VALUES (1,3,'j'), (20,8,'e');
+EXPLAIN SELECT alias2.i1
+FROM t1 AS alias1 STRAIGHT_JOIN t1 AS alias2
+ON alias2.pk AND alias2.pk <= alias1.c1
+WHERE alias2.pk = 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	alias1	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	alias2	const	PRIMARY	PRIMARY	4	const	1	Using index condition
+SELECT alias2.i1
+FROM t1 AS alias1 STRAIGHT_JOIN t1 AS alias2
+ON alias2.pk AND alias2.pk <= alias1.c1
+WHERE alias2.pk = 1;
+i1
+Warnings:
+Warning	1292	Truncated incorrect DOUBLE value: 'j'
+DROP TABLE t1;
 set default_storage_engine= @save_storage_engine;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/innodb_icp_none.result'
--- a/mysql-test/r/innodb_icp_none.result	2011-06-09 06:22:39 +0000
+++ b/mysql-test/r/innodb_icp_none.result	2011-08-03 07:21:17 +0000
@@ -911,5 +911,31 @@
 pk
 DROP VIEW v1;
 DROP TABLE t1;
+#
+# BUG#12601961 "SEGFAULT IN HANDLER::COMPARE_KEY2"
+#
+CREATE TABLE t1 (
+pk INTEGER NOT NULL, 
+i1 INTEGER NOT NULL,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t1 VALUES (1,3,'j'), (20,8,'e');
+EXPLAIN SELECT alias2.i1
+FROM t1 AS alias1 STRAIGHT_JOIN t1 AS alias2
+ON alias2.pk AND alias2.pk <= alias1.c1
+WHERE alias2.pk = 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	alias1	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	alias2	const	PRIMARY	PRIMARY	4	const	1	Using where
+SELECT alias2.i1
+FROM t1 AS alias1 STRAIGHT_JOIN t1 AS alias2
+ON alias2.pk AND alias2.pk <= alias1.c1
+WHERE alias2.pk = 1;
+i1
+Warnings:
+Warning	1292	Truncated incorrect DOUBLE value: 'j'
+Warning	1292	Truncated incorrect DOUBLE value: 'e'
+DROP TABLE t1;
 set default_storage_engine= @save_storage_engine;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_icp.result'
--- a/mysql-test/r/myisam_icp.result	2011-06-09 06:22:39 +0000
+++ b/mysql-test/r/myisam_icp.result	2011-08-03 07:21:17 +0000
@@ -907,4 +907,7 @@
 pk
 DROP VIEW v1;
 DROP TABLE t1;
+#
+# BUG#12601961 "SEGFAULT IN HANDLER::COMPARE_KEY2"
+#
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_icp_none.result'
--- a/mysql-test/r/myisam_icp_none.result	2011-06-09 06:22:39 +0000
+++ b/mysql-test/r/myisam_icp_none.result	2011-08-03 07:21:17 +0000
@@ -906,4 +906,7 @@
 pk
 DROP VIEW v1;
 DROP TABLE t1;
+#
+# BUG#12601961 "SEGFAULT IN HANDLER::COMPARE_KEY2"
+#
 set optimizer_switch=default;

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2011-07-28 10:54:44 +0000
+++ b/sql/handler.cc	2011-08-03 07:21:17 +0000
@@ -2321,6 +2321,7 @@
   int result;
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(end_range == NULL);
   MYSQL_TABLE_WAIT_VARIABLES(locker, state) /* no ';' */
 
   MYSQL_START_TABLE_IO_WAIT(locker, &state, m_psi,

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2011-07-20 14:40:52 +0000
+++ b/sql/handler.h	2011-08-03 07:21:17 +0000
@@ -1314,9 +1314,22 @@
   bool mrr_have_range;
   /* Current range (the one we're now returning rows from) */
   KEY_MULTI_RANGE mrr_cur_range;
-  
-  /** The following are for read_range() */
-  key_range save_end_range, *end_range;
+
+protected:
+  /*
+    Storage space for the end range value. Should only be accessed using
+    the end_range pointer. The content is invalid when end_range is NULL.
+  */
+  key_range save_end_range;
+
+public:  
+  /*
+    End value for a range scan. If this is NULL the range scan has no
+    end value. Should also be NULL when there is no ongoing range scan.
+    Used by the read_range() functions and also evaluated by pushed
+    index conditions.
+  */
+  key_range *end_range;
   KEY_PART_INFO *range_key_part;
   int key_compare_result_on_equal;
   bool eq_range;
@@ -1400,7 +1413,7 @@
   handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
     :table_share(share_arg), table(0),
     estimation_rows_to_insert(0), ht(ht_arg),
-    ref(0), in_range_check_pushed_down(FALSE),
+    ref(0), end_range(NULL), in_range_check_pushed_down(false),
     key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
     ref_length(sizeof(my_off_t)),
     ft_handler(0), inited(NONE),

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (olav.sandstaa:3337 to 3338) Bug#12601961Olav Sandstaa3 Aug