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#12601961 | Olav Sandstaa | 3 Aug |