mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-24907: Empty the source list after merging an Item_equal
With save_merged false, Item_equal::merge_into_list() merges this object's Item_equal instances into another, linking *this object's items into the target. However this allowed callers to free an item via one list but later read it through the other; a case of use-after-free. If save_merged is false then delete the items from the source.
This commit is contained in:
committed by
Dave Gosselin
parent
e79cd93f79
commit
a11e9e7e9c
@@ -2754,6 +2754,30 @@ SELECT * FROM t1 WHERE (0,0) IN (SELECT MAX(c),MIN(c) FROM t1);
|
||||
c
|
||||
0
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-24907: Empty the source list after merging an Item_equal
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (0,0);
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (2),(0);
|
||||
CREATE TABLE t3 (d INT) ENGINE=MyISAM;
|
||||
INSERT INTO t3 VALUES (1),(3);
|
||||
SELECT * FROM t1 LEFT JOIN (
|
||||
t2 JOIN t3 ON (t3.d = t2.c)
|
||||
) ON (
|
||||
t1.b NOT IN (SELECT d FROM t3)
|
||||
) WHERE (t1.a, t3.d) IN (SELECT c, MAX(c) FROM t2) AND t1.a = t1.b;
|
||||
a b c d
|
||||
SELECT * FROM t1 LEFT JOIN (
|
||||
t2 JOIN t3 ON (t3.d = t2.c)
|
||||
) ON (
|
||||
t1.b > 3
|
||||
) WHERE t1.a IN (SELECT MAX(c) FROM t2 GROUP BY c) AND
|
||||
t3.d IN (SELECT COUNT(c) FROM t2 GROUP BY c) AND
|
||||
t1.a = t1.b;
|
||||
a b c d
|
||||
DROP TABLE t1, t2, t3;
|
||||
# end of 10.11 tests
|
||||
set @subselect_mat_test_optimizer_switch_value=null;
|
||||
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
|
||||
|
||||
@@ -2796,4 +2796,28 @@ SELECT * FROM t1 WHERE (0,0) IN (SELECT MAX(c),MIN(c) FROM t1);
|
||||
c
|
||||
0
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-24907: Empty the source list after merging an Item_equal
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (0,0);
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (2),(0);
|
||||
CREATE TABLE t3 (d INT) ENGINE=MyISAM;
|
||||
INSERT INTO t3 VALUES (1),(3);
|
||||
SELECT * FROM t1 LEFT JOIN (
|
||||
t2 JOIN t3 ON (t3.d = t2.c)
|
||||
) ON (
|
||||
t1.b NOT IN (SELECT d FROM t3)
|
||||
) WHERE (t1.a, t3.d) IN (SELECT c, MAX(c) FROM t2) AND t1.a = t1.b;
|
||||
a b c d
|
||||
SELECT * FROM t1 LEFT JOIN (
|
||||
t2 JOIN t3 ON (t3.d = t2.c)
|
||||
) ON (
|
||||
t1.b > 3
|
||||
) WHERE t1.a IN (SELECT MAX(c) FROM t2 GROUP BY c) AND
|
||||
t3.d IN (SELECT COUNT(c) FROM t2 GROUP BY c) AND
|
||||
t1.a = t1.b;
|
||||
a b c d
|
||||
DROP TABLE t1, t2, t3;
|
||||
# end of 10.11 tests
|
||||
|
||||
@@ -2472,4 +2472,31 @@ SELECT * FROM t1 WHERE (0,0) IN (SELECT MAX(c),MIN(c) FROM t1);
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24907: Empty the source list after merging an Item_equal
|
||||
--echo #
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (0,0);
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (2),(0);
|
||||
CREATE TABLE t3 (d INT) ENGINE=MyISAM;
|
||||
INSERT INTO t3 VALUES (1),(3);
|
||||
|
||||
# Result should be empty.
|
||||
SELECT * FROM t1 LEFT JOIN (
|
||||
t2 JOIN t3 ON (t3.d = t2.c)
|
||||
) ON (
|
||||
t1.b NOT IN (SELECT d FROM t3)
|
||||
) WHERE (t1.a, t3.d) IN (SELECT c, MAX(c) FROM t2) AND t1.a = t1.b;
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN (
|
||||
t2 JOIN t3 ON (t3.d = t2.c)
|
||||
) ON (
|
||||
t1.b > 3
|
||||
) WHERE t1.a IN (SELECT MAX(c) FROM t2 GROUP BY c) AND
|
||||
t3.d IN (SELECT COUNT(c) FROM t2 GROUP BY c) AND
|
||||
t1.a = t1.b;
|
||||
|
||||
DROP TABLE t1, t2, t3;
|
||||
|
||||
--echo # end of 10.11 tests
|
||||
|
||||
@@ -7233,7 +7233,17 @@ void Item_equal::merge_into_list(THD *thd, List<Item_equal> *list,
|
||||
if (!merge_into)
|
||||
{
|
||||
if (item->merge_with_check(thd, this, save_merged))
|
||||
{
|
||||
merge_into= item;
|
||||
/*
|
||||
If the caller doesn't set save_merged, then remove the items from the
|
||||
source, which is 'this' object. That prevents an ASAN problem where
|
||||
an item appearing in both lists has its memory deleted via one list
|
||||
and then is later read via the other.
|
||||
*/
|
||||
if (!save_merged)
|
||||
equal_items.empty();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user