MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats
Expression_cache_tmptable object uses an Expression_cache_tracker object to report the statistics. In the common scenario, Expression_cache_tmptable destructor sets tracker->cache=NULL. The tracker object survives after the expression cache is deleted and one may call cache_tracker->fetch_current_stats() for it with no harm. However a degenerate cache with no parameters does not set tracker->cache=NULL in Expression_cache_tmptable destructor which results in an attempt to use freed data in the cache_tracker->fetch_current_stats() call. Fixed by setting tracker->cache to NULL and wrapping the assignment into a function.
This commit is contained in:
parent
c711abd182
commit
eea15803ec
@ -2841,4 +2841,79 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
2 DEPENDENT SUBQUERY tn eq_ref PRIMARY PRIMARY 32 test.tms.key1 1 Using where
|
||||
set optimizer_switch=@tmp_os;
|
||||
drop table t1, t10, t11;
|
||||
#
|
||||
# MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
INSERT INTO t1 VALUES (1,2),(3,4);
|
||||
ANALYZE FORMAT=JSON
|
||||
SELECT DISTINCT
|
||||
(SELECT MIN(a) FROM t1 WHERE b <= ANY (SELECT a FROM t1)) AS f
|
||||
FROM t1;
|
||||
ANALYZE
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"duplicate_removal": {
|
||||
"temporary_table": {
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"r_loops": 1,
|
||||
"rows": 2,
|
||||
"r_rows": 2,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"filtered": 100,
|
||||
"r_filtered": 100
|
||||
},
|
||||
"subqueries": [
|
||||
{
|
||||
"expression_cache": {
|
||||
"state": "disabled",
|
||||
"r_loops": 0,
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"r_loops": 1,
|
||||
"rows": 2,
|
||||
"r_rows": 2,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"filtered": 100,
|
||||
"r_filtered": 50,
|
||||
"attached_condition": "<nop>(<in_optimizer>(t1.b,(subquery#3) >= 4))"
|
||||
},
|
||||
"subqueries": [
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 3,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"r_loops": 1,
|
||||
"rows": 2,
|
||||
"r_rows": 2,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"filtered": 100,
|
||||
"r_filtered": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DROP TABLE t1;
|
||||
# End of 10.2 tests
|
||||
|
@ -2351,4 +2351,19 @@ set optimizer_switch=@tmp_os;
|
||||
|
||||
drop table t1, t10, t11;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats
|
||||
--echo #
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
INSERT INTO t1 VALUES (1,2),(3,4);
|
||||
|
||||
--source include/analyze-format.inc
|
||||
ANALYZE FORMAT=JSON
|
||||
SELECT DISTINCT
|
||||
(SELECT MIN(a) FROM t1 WHERE b <= ANY (SELECT a FROM t1)) AS f
|
||||
FROM t1;
|
||||
|
||||
# Cleanup
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # End of 10.2 tests
|
||||
|
@ -63,7 +63,7 @@ void Expression_cache_tmptable::disable_cache()
|
||||
cache_table= NULL;
|
||||
update_tracker();
|
||||
if (tracker)
|
||||
tracker->cache= NULL;
|
||||
tracker->detach_from_cache();
|
||||
}
|
||||
|
||||
|
||||
@ -188,6 +188,8 @@ Expression_cache_tmptable::~Expression_cache_tmptable()
|
||||
else
|
||||
{
|
||||
update_tracker();
|
||||
if (tracker)
|
||||
tracker->detach_from_cache();
|
||||
tracker= NULL;
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,11 @@ public:
|
||||
cache(c), hit(0), miss(0), state(UNINITED)
|
||||
{}
|
||||
|
||||
private:
|
||||
// This can be NULL if the cache is already deleted
|
||||
Expression_cache *cache;
|
||||
|
||||
public:
|
||||
ulong hit, miss;
|
||||
enum expr_cache_state state;
|
||||
|
||||
@ -91,6 +95,7 @@ public:
|
||||
void set(ulong h, ulong m, enum expr_cache_state s)
|
||||
{hit= h; miss= m; state= s;}
|
||||
|
||||
void detach_from_cache() { cache= NULL; }
|
||||
void fetch_current_stats()
|
||||
{
|
||||
if (cache)
|
||||
|
Loading…
x
Reference in New Issue
Block a user