diff --git a/src/main/capi/scalar_function-c.cpp b/src/main/capi/scalar_function-c.cpp index 1653b19450e4..89625b28765e 100644 --- a/src/main/capi/scalar_function-c.cpp +++ b/src/main/capi/scalar_function-c.cpp @@ -354,9 +354,14 @@ duckdb_expression duckdb_scalar_function_bind_get_argument(duckdb_bind_info info return nullptr; } auto &bind_info = GetCScalarFunctionBindInfo(info); - auto wrapper = new ExpressionWrapper(); - wrapper->expr = bind_info.arguments[index]->Copy(); - return reinterpret_cast(wrapper); + try { + auto wrapper = duckdb::make_uniq(); + wrapper->expr = bind_info.arguments[index]->Copy(); + return reinterpret_cast(wrapper.release()); + } catch (std::exception &e) { + duckdb_scalar_function_bind_set_error(info, e.what()); + return nullptr; + } } void duckdb_scalar_function_set_extra_info(duckdb_scalar_function function, void *extra_info, diff --git a/test/api/capi/capi_scalar_functions.cpp b/test/api/capi/capi_scalar_functions.cpp index 60476f6f1121..401bd75b6b5f 100644 --- a/test/api/capi/capi_scalar_functions.cpp +++ b/test/api/capi/capi_scalar_functions.cpp @@ -558,6 +558,13 @@ TEST_CASE("Test Scalar Function with Bind Info", "[capi]") { result = tester.Query("SELECT get_connection_id(200::UTINYINT + 200::UTINYINT)"); REQUIRE_FAIL(result); REQUIRE(StringUtil::Contains(result->ErrorMessage(), "Overflow in addition of")); + + // Correlated subquery as argument: BoundSubqueryExpression::Copy() throws SerializationException. + // Before the fix, this exception escaped the C API boundary and called std::terminate() because + // Go's CGo frames (and plain C callers) have no C++ unwind tables. The fix catches at the C + // boundary and surfaces it as a normal query error. + result = tester.Query("SELECT get_connection_id((SELECT 42::UBIGINT)) FROM (VALUES(1)) t(x)"); + REQUIRE_FAIL(result); } TEST_CASE("Test volatile scalar function with bind in WHERE clause", "[capi]") {