Description:
mysqld terminates with SIGSEGV (signal 11) while executing a SELECT whose WHERE clause contains correlated subqueries evaluated via the dynamic range access method ("Range checked for each record").
Backtrace (symbol names; observed on a build based on 8.0.46):
```
bitmap_copy mysys/my_bitmap.cc
fill_used_fields_bitmap sql/range_optimizer/range_optimizer.cc
test_quick_select sql/range_optimizer/range_optimizer.cc
DynamicRangeIterator::Init sql/iterators/ref_row_iterators.cc
LimitOffsetIterator::Init sql/iterators/composite_iterators.cc
Query_expression::ExecuteIteratorQuery sql/sql_union.cc
Query_expression::execute sql/sql_union.cc
SubqueryWithResult::exec sql/item_subselect.cc
Item_subselect::exec sql/item_subselect.cc
Item_exists_subselect::val_bool sql/item_subselect.cc
Item_cond_or::val_int sql/item_cmpfunc.cc
FilterIterator::Read sql/iterators/composite_iterators.cc
TemptableAggregateIterator<...>::Init sql/iterators/composite_iterators.cc
MaterializeIterator<...>::MaterializeQueryBlock sql/iterators/composite_iterators.cc
MaterializeIterator<...>::Init sql/iterators/composite_iterators.cc
TemptableAggregateIterator<...>::Init sql/iterators/composite_iterators.cc
filesort sql/filesort.cc
SortingIterator::DoSort sql/iterators/sorting_iterator.cc
SortingIterator::Init sql/iterators/sorting_iterator.cc
LimitOffsetIterator::Init sql/iterators/composite_iterators.cc
Query_expression::ExecuteIteratorQuery sql/sql_union.cc
Query_expression::execute sql/sql_union.cc
```
The crash is in fill_used_fields_bitmap(), at the call bitmap_copy(needed_fields, table->read_set). The read_set bitmap appears to be invalid at that point. In release builds the assertions inside bitmap_copy() are compiled out, so the invalid pointer reaches the copy loop and faults instead of aborting.
The affected code path is reached only when DynamicRangeIterator re-invokes test_quick_select() per outer row for a correlated subquery. The subquery's join predicate wraps the indexed column in functions (TRIM/NULLIF/COALESCE), which prevents a plan-time index lookup and forces the per-record range strategy.
How to repeat:
The reproduction step has customer data so I generated a generic sample query with customer data erased.
```
CREATE DATABASE bugtest;
USE bugtest;
CREATE TABLE t_stats (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
c1 VARCHAR(16),
k1 BIGINT,
k2 INT,
k4 INT,
k3 BIGINT,
d DATE,
cnt INT,
v1 DECIMAL(20,4),
v2 DECIMAL(20,4),
v3 DECIMAL(20,4),
KEY idx_cover (k1, k2, k4, d, k3, cnt, v1, v2, v3, c1)
) ENGINE=InnoDB;
CREATE TABLE t_lookup (
id BIGINT PRIMARY KEY,
k2 INT,
gkey VARCHAR(64),
KEY idx_id_k2 (id, k2)
) ENGINE=InnoDB;
CREATE TABLE t_orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
st TINYINT,
k1 BIGINT,
k2 INT,
k4 INT,
gkey VARCHAR(64),
ts DATETIME,
c1 VARCHAR(16),
acct VARCHAR(64),
nm1 VARCHAR(64),
nm2 VARCHAR(64),
v1 DECIMAL(20,4),
v2 DECIMAL(20,4),
v3 DECIMAL(20,4),
KEY idx_k1_k2_ts (k1, k2, ts),
KEY idx_st_ts (st, ts),
KEY idx_gkey (gkey)
) ENGINE=InnoDB;
```
# Insert a big amount of data in these tables.
```
SELECT c1, MAX(f1) AS f1, mid, MAX(acct) AS acct, MAX(lvl) AS lvl, k2, k4,
MAX(gk) AS gk, MAX(f2) AS f2, MAX(nm1) AS nm1, MAX(nm2) AS nm2,
SUM(cnt) AS cnt, SUM(v1) AS v1, SUM(v2) AS v2, SUM(v3) AS v3
FROM (
SELECT p.c1 AS c1,
CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f1,
p.k1 AS mid,
COALESCE(NULLIF(MAX(CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci),''),'') AS acct,
0 AS lvl, p.k2 AS k2, p.k4 AS k4,
CAST((COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR))) AS CHAR CHARACTER SET utf8mb4) COLLATE
utf8mb4_unicode_ci AS gk,
CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f2,
CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm1,
CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm2,
SUM(p.cnt) AS cnt, SUM(p.v1) AS v1, SUM(p.v2) AS v2, SUM(p.v3) AS v3
FROM t_stats p FORCE INDEX(idx_cover)
LEFT JOIN t_lookup g ON g.id = p.k3 AND g.k2 = p.k2
WHERE p.d BETWEEN '2026-08-28' AND '2026-09-02'
AND NOT (
p.d = '2026-09-02'
AND EXISTS (
SELECT 1 FROM t_orders o
WHERE o.st = 1 AND o.k1 = p.k1 AND o.k2 = p.k2
AND COALESCE(NULLIF(TRIM(o.gkey),''),'')
= COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR))
AND o.ts >= '2026-09-02 16:00:00' Jump to bottom (ctrl+End) ↓ 9:59'
)
AND (
SELECT COUNT(*) FROM t_orders o2
WHERE o2.st = 1 AND o2.k1 = p.k1 AND o2.k2 = p.k2
AND COALESCE(NULLIF(TRIM(o2.gkey),''),'')
= COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR))
AND o2.ts >= '2026-08-27 16:00:00' AND o2.ts <= '2026-09-03 15:59:59'
) = p.cnt
)
GROUP BY p.c1, p.k1, p.k2, p.k4,
CAST((COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR))) AS CHAR CHARACTER SET utf8mb4) COLLATE
utf8mb4_unicode_ci
UNION ALL
SELECT COALESCE(NULLIF(o.c1,''),'CNY') AS c1,
CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f1,
o.k1 AS mid,
CAST((COALESCE(NULLIF(o.acct,''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS acct,
0 AS lvl, o.k2 AS k2, COALESCE(NULLIF(o.k4,0),0) AS k4,
CAST((COALESCE(NULLIF(TRIM(o.gkey),''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS gk,
CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f2,
CAST((COALESCE(NULLIF(TRIM(o.nm1),''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm1,
CAST((COALESCE(NULLIF(TRIM(o.nm2),''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm2,
COUNT(1) AS cnt, COALESCE(SUM(o.v1),0) AS v1,
COALESCE(SUM(o.v2),0) AS v2, COALESCE(SUM(o.v3),0) AS v3
FROM t_orders o
WHERE o.st = 1 AND o.ts >= '2026-09-02 16:00:00' AND o.ts <= '2026-09-03 15:59:59'
GROUP BY COALESCE(NULLIF(o.c1,''),'CNY'), o.k1, acct, o.k2, o.k4, nm1, nm2, gk
) combined
GROUP BY c1, mid, k2, k4, gk
ORDER BY v2 DESC
LIMIT 0, 50;
```
Description: mysqld terminates with SIGSEGV (signal 11) while executing a SELECT whose WHERE clause contains correlated subqueries evaluated via the dynamic range access method ("Range checked for each record"). Backtrace (symbol names; observed on a build based on 8.0.46): ``` bitmap_copy mysys/my_bitmap.cc fill_used_fields_bitmap sql/range_optimizer/range_optimizer.cc test_quick_select sql/range_optimizer/range_optimizer.cc DynamicRangeIterator::Init sql/iterators/ref_row_iterators.cc LimitOffsetIterator::Init sql/iterators/composite_iterators.cc Query_expression::ExecuteIteratorQuery sql/sql_union.cc Query_expression::execute sql/sql_union.cc SubqueryWithResult::exec sql/item_subselect.cc Item_subselect::exec sql/item_subselect.cc Item_exists_subselect::val_bool sql/item_subselect.cc Item_cond_or::val_int sql/item_cmpfunc.cc FilterIterator::Read sql/iterators/composite_iterators.cc TemptableAggregateIterator<...>::Init sql/iterators/composite_iterators.cc MaterializeIterator<...>::MaterializeQueryBlock sql/iterators/composite_iterators.cc MaterializeIterator<...>::Init sql/iterators/composite_iterators.cc TemptableAggregateIterator<...>::Init sql/iterators/composite_iterators.cc filesort sql/filesort.cc SortingIterator::DoSort sql/iterators/sorting_iterator.cc SortingIterator::Init sql/iterators/sorting_iterator.cc LimitOffsetIterator::Init sql/iterators/composite_iterators.cc Query_expression::ExecuteIteratorQuery sql/sql_union.cc Query_expression::execute sql/sql_union.cc ``` The crash is in fill_used_fields_bitmap(), at the call bitmap_copy(needed_fields, table->read_set). The read_set bitmap appears to be invalid at that point. In release builds the assertions inside bitmap_copy() are compiled out, so the invalid pointer reaches the copy loop and faults instead of aborting. The affected code path is reached only when DynamicRangeIterator re-invokes test_quick_select() per outer row for a correlated subquery. The subquery's join predicate wraps the indexed column in functions (TRIM/NULLIF/COALESCE), which prevents a plan-time index lookup and forces the per-record range strategy. How to repeat: The reproduction step has customer data so I generated a generic sample query with customer data erased. ``` CREATE DATABASE bugtest; USE bugtest; CREATE TABLE t_stats ( id BIGINT AUTO_INCREMENT PRIMARY KEY, c1 VARCHAR(16), k1 BIGINT, k2 INT, k4 INT, k3 BIGINT, d DATE, cnt INT, v1 DECIMAL(20,4), v2 DECIMAL(20,4), v3 DECIMAL(20,4), KEY idx_cover (k1, k2, k4, d, k3, cnt, v1, v2, v3, c1) ) ENGINE=InnoDB; CREATE TABLE t_lookup ( id BIGINT PRIMARY KEY, k2 INT, gkey VARCHAR(64), KEY idx_id_k2 (id, k2) ) ENGINE=InnoDB; CREATE TABLE t_orders ( id BIGINT AUTO_INCREMENT PRIMARY KEY, st TINYINT, k1 BIGINT, k2 INT, k4 INT, gkey VARCHAR(64), ts DATETIME, c1 VARCHAR(16), acct VARCHAR(64), nm1 VARCHAR(64), nm2 VARCHAR(64), v1 DECIMAL(20,4), v2 DECIMAL(20,4), v3 DECIMAL(20,4), KEY idx_k1_k2_ts (k1, k2, ts), KEY idx_st_ts (st, ts), KEY idx_gkey (gkey) ) ENGINE=InnoDB; ``` # Insert a big amount of data in these tables. ``` SELECT c1, MAX(f1) AS f1, mid, MAX(acct) AS acct, MAX(lvl) AS lvl, k2, k4, MAX(gk) AS gk, MAX(f2) AS f2, MAX(nm1) AS nm1, MAX(nm2) AS nm2, SUM(cnt) AS cnt, SUM(v1) AS v1, SUM(v2) AS v2, SUM(v3) AS v3 FROM ( SELECT p.c1 AS c1, CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f1, p.k1 AS mid, COALESCE(NULLIF(MAX(CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci),''),'') AS acct, 0 AS lvl, p.k2 AS k2, p.k4 AS k4, CAST((COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR))) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS gk, CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f2, CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm1, CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm2, SUM(p.cnt) AS cnt, SUM(p.v1) AS v1, SUM(p.v2) AS v2, SUM(p.v3) AS v3 FROM t_stats p FORCE INDEX(idx_cover) LEFT JOIN t_lookup g ON g.id = p.k3 AND g.k2 = p.k2 WHERE p.d BETWEEN '2026-08-28' AND '2026-09-02' AND NOT ( p.d = '2026-09-02' AND EXISTS ( SELECT 1 FROM t_orders o WHERE o.st = 1 AND o.k1 = p.k1 AND o.k2 = p.k2 AND COALESCE(NULLIF(TRIM(o.gkey),''),'') = COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR)) AND o.ts >= '2026-09-02 16:00:00' Jump to bottom (ctrl+End) ↓ 9:59' ) AND ( SELECT COUNT(*) FROM t_orders o2 WHERE o2.st = 1 AND o2.k1 = p.k1 AND o2.k2 = p.k2 AND COALESCE(NULLIF(TRIM(o2.gkey),''),'') = COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR)) AND o2.ts >= '2026-08-27 16:00:00' AND o2.ts <= '2026-09-03 15:59:59' ) = p.cnt ) GROUP BY p.c1, p.k1, p.k2, p.k4, CAST((COALESCE(NULLIF(TRIM(g.gkey),''), CAST(p.k3 AS CHAR))) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci UNION ALL SELECT COALESCE(NULLIF(o.c1,''),'CNY') AS c1, CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f1, o.k1 AS mid, CAST((COALESCE(NULLIF(o.acct,''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS acct, 0 AS lvl, o.k2 AS k2, COALESCE(NULLIF(o.k4,0),0) AS k4, CAST((COALESCE(NULLIF(TRIM(o.gkey),''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS gk, CAST(('') AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS f2, CAST((COALESCE(NULLIF(TRIM(o.nm1),''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm1, CAST((COALESCE(NULLIF(TRIM(o.nm2),''),'')) AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci AS nm2, COUNT(1) AS cnt, COALESCE(SUM(o.v1),0) AS v1, COALESCE(SUM(o.v2),0) AS v2, COALESCE(SUM(o.v3),0) AS v3 FROM t_orders o WHERE o.st = 1 AND o.ts >= '2026-09-02 16:00:00' AND o.ts <= '2026-09-03 15:59:59' GROUP BY COALESCE(NULLIF(o.c1,''),'CNY'), o.k1, acct, o.k2, o.k4, nm1, nm2, gk ) combined GROUP BY c1, mid, k2, k4, gk ORDER BY v2 DESC LIMIT 0, 50; ```