Skip to content

Conversation

@hrl20
Copy link
Collaborator

@hrl20 hrl20 commented Jul 17, 2025

Reproducing issue #257, the segfault was consistently occurring in the duckdb_destroy_result here

void Execute() override {
result_ptr_ = reinterpret_cast<duckdb_result*>(duckdb_malloc(sizeof(duckdb_result)));
result_ptr_->internal_data = nullptr;
if (duckdb_execute_prepared(prepared_statement_, result_ptr_)) {
auto error = duckdb_result_error(result_ptr_);
if (error) {
SetError(error);
} else {
SetError("Failed to execute prepared statement");
}
duckdb_destroy_result(result_ptr_);
duckdb_free(result_ptr_);
result_ptr_ = nullptr;
}
}

Looking into what duckdby_destroy_result does: https://github.com/duckdb/duckdb/blob/879b0e72286b189a38b969214aa7a4e26cb64fff/src/main/capi/result-c.cpp#L498-L511
The theory is that because result->deprecated_columns is uninitialized in the caller and may contain arbitrary value. In the error path, deprecated_columns may never end up being initialized and will lead to duckdby_destroy_result trying to access the arbitrary address it holds.

Testing

The added unit test models after the repro script and was consistently crashing without this fix. With the fix it does not crash.

Copy link
Collaborator

@jraymakers jraymakers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test takes a bit long to run (~500ms); maybe we can get that lower in the future. But this fix is important and the test run time is a minor issue that we can look into later, so I'm good with merging this as-is. Thanks a bunch for tracking this down!

@jraymakers jraymakers merged commit 7458a8c into duckdb:main Jul 19, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants