From 51c89057a00cb2be187eb069db4b770f07d5ccb3 Mon Sep 17 00:00:00 2001 From: Anway Durge Date: Mon, 19 Oct 2026 23:09:32 +0530 Subject: [PATCH] MDEV-40868: Do not let C++ exceptions leave send_data Catch DuckDB conversion exceptions in send_data, raise a MariaDB error, and return -1. --- .../mysql-test/duckdb/r/mdev_40868.result | 11 +++++ .../mysql-test/duckdb/t/mdev_40868.test | 25 ++++++++++ storage/duckdb/runtime/fiber_scan.cc | 48 ++++++++++++------- 3 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 storage/duckdb/mysql-test/duckdb/r/mdev_40868.result create mode 100644 storage/duckdb/mysql-test/duckdb/t/mdev_40868.test diff --git a/storage/duckdb/mysql-test/duckdb/r/mdev_40868.result b/storage/duckdb/mysql-test/duckdb/r/mdev_40868.result new file mode 100644 index 0000000000000..8d3526aca37b3 --- /dev/null +++ b/storage/duckdb/mysql-test/duckdb/r/mdev_40868.result @@ -0,0 +1,11 @@ +call mtr.add_suppression("FIBER: execution error"); +CREATE TABLE t1 (c2 DATETIME); +INSERT INTO t1 VALUES ('0000-00-00'); +CREATE TABLE t2 (c1 INT PRIMARY KEY) ENGINE=DuckDB; +SELECT * FROM t2 UNION SELECT * FROM t1; +c1 +SELECT 1 AS still_alive; +still_alive +1 +DROP TABLE t2; +DROP TABLE t1; diff --git a/storage/duckdb/mysql-test/duckdb/t/mdev_40868.test b/storage/duckdb/mysql-test/duckdb/t/mdev_40868.test new file mode 100644 index 0000000000000..2950944a7e0a5 --- /dev/null +++ b/storage/duckdb/mysql-test/duckdb/t/mdev_40868.test @@ -0,0 +1,25 @@ +--source ../include/have_duckdb.inc +--source include/not_msan.inc +--disable_warnings + +# +# MDEV-40868 SIGABRT in duckdb::Value::CastAs on UNION of DuckDB +# and InnoDB table. Invalid DATETIME '0000-00-00' used to throw +# out of select_to_duckdb::send_data and abort the server. +# send_data now converts the exception into a THD error and returns +# -1; the fiber scan finishes without crashing. +# + +call mtr.add_suppression("FIBER: execution error"); + +CREATE TABLE t1 (c2 DATETIME); +INSERT INTO t1 VALUES ('0000-00-00'); +CREATE TABLE t2 (c1 INT PRIMARY KEY) ENGINE=DuckDB; + +SELECT * FROM t2 UNION SELECT * FROM t1; + +# Server must still be usable after the conversion error. +SELECT 1 AS still_alive; + +DROP TABLE t2; +DROP TABLE t1; diff --git a/storage/duckdb/runtime/fiber_scan.cc b/storage/duckdb/runtime/fiber_scan.cc index 588786f2feef7..cfdf4d9147e37 100644 --- a/storage/duckdb/runtime/fiber_scan.cc +++ b/storage/duckdb/runtime/fiber_scan.cc @@ -102,29 +102,43 @@ select_to_duckdb::select_to_duckdb(THD *thd_arg, int select_to_duckdb::send_data(List &items) { - List_iterator_fast it(items); - Item *item; - duckdb::idx_t col= 0; - - while ((item= it++)) + try { - if (col < types_->size()) + List_iterator_fast it(items); + Item *item; + duckdb::idx_t col= 0; + + while ((item= it++)) { - duckdb::Value val= item_to_duckdb_value(item, (*types_)[col]); - buffer_->data[col].SetValue(row_count_, val); + if (col < types_->size()) + { + duckdb::Value val= item_to_duckdb_value(item, (*types_)[col]); + buffer_->data[col].SetValue(row_count_, val); + } + col++; + } + row_count_++; + + if (row_count_ >= STANDARD_VECTOR_SIZE) + { + buffer_->SetCardinality(row_count_); + row_count_= 0; + fiber_context_yield(ctx_); } - col++; - } - row_count_++; - if (row_count_ >= STANDARD_VECTOR_SIZE) + return thd->killed ? -1 : 0; + } + catch (const std::exception &ex) { - buffer_->SetCardinality(row_count_); - row_count_= 0; - fiber_context_yield(ctx_); + my_error(ER_GET_ERRMSG, MYF(0), HA_ERR_GENERIC, ex.what(), "DuckDB"); + return -1; + } + catch (...) + { + my_error(ER_GET_ERRMSG, MYF(0), HA_ERR_GENERIC, + "Unknown error converting row to DuckDB", "DuckDB"); + return -1; } - - return thd->killed ? -1 : 0; } bool select_to_duckdb::send_eof()