Skip to content

Commit a2aab47

Browse files
authored
fix: bound column name ref leak (#3646)
`duckdb_vx_expr_get_bound_column_ref_get_name` returns a heap allocated string that needs to freed with `duckdb_free`. --------- Signed-off-by: Alexander Droste <[email protected]>
1 parent d17d830 commit a2aab47

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

vortex-duckdb/src/duckdb/expr.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::ptr;
44

55
use crate::cpp::duckdb_vx_expr_class;
66
use crate::duckdb::{ScalarFunction, Value};
7-
use crate::{cpp, wrapper};
7+
use crate::{cpp, duckdb, wrapper};
88

99
wrapper!(Expression, cpp::duckdb_vx_expr, cpp::duckdb_vx_destroy_expr);
1010

@@ -30,8 +30,9 @@ impl Expression {
3030
cpp::DUCKDB_VX_EXPR_CLASS::DUCKDB_VX_EXPR_CLASS_BOUND_COLUMN_REF => {
3131
let ptr =
3232
unsafe { cpp::duckdb_vx_expr_get_bound_column_ref_get_name(self.as_ptr()) };
33+
3334
ExpressionClass::BoundColumnRef(BoundColumnRef {
34-
name: unsafe { CStr::from_ptr(ptr) },
35+
name: duckdb::string::String::from_ptr(ptr),
3536
})
3637
}
3738
cpp::DUCKDB_VX_EXPR_CLASS::DUCKDB_VX_EXPR_CLASS_BOUND_CONSTANT => {
@@ -133,7 +134,7 @@ impl Expression {
133134
}
134135

135136
pub enum ExpressionClass<'a> {
136-
BoundColumnRef(BoundColumnRef<'a>),
137+
BoundColumnRef(BoundColumnRef),
137138
BoundConstant(BoundConstant),
138139
BoundComparison(BoundComparison),
139140
BoundConjunction(BoundConjunction<'a>),
@@ -142,8 +143,8 @@ pub enum ExpressionClass<'a> {
142143
BoundFunction(BoundFunction<'a>),
143144
}
144145

145-
pub struct BoundColumnRef<'a> {
146-
pub name: &'a CStr,
146+
pub struct BoundColumnRef {
147+
pub name: duckdb::string::String,
147148
}
148149

149150
pub struct BoundConstant {

vortex-duckdb/src/duckdb/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod logical_type;
77
mod query_result;
88
mod scalar_function;
99
mod selection_vector;
10+
mod string;
1011
mod table_filter;
1112
mod table_function;
1213
mod value;
@@ -24,6 +25,7 @@ pub use logical_type::*;
2425
pub use query_result::*;
2526
pub use scalar_function::*;
2627
pub use selection_vector::*;
28+
pub use string::*;
2729
pub use table_filter::*;
2830
pub use table_function::*;
2931
pub use value::*;

vortex-duckdb/src/duckdb/string.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::ffi::{CStr, c_char};
2+
use std::fmt::{Debug, Display, Formatter};
3+
use std::str::Utf8Error;
4+
5+
use crate::cpp;
6+
7+
/// Wraps a heap allocated DuckDB string.
8+
pub struct String {
9+
ptr: *const c_char,
10+
}
11+
12+
impl String {
13+
pub fn from_ptr(ptr: *const c_char) -> Self {
14+
String { ptr }
15+
}
16+
17+
pub fn as_cstr(&self) -> &CStr {
18+
unsafe { CStr::from_ptr(self.ptr) }
19+
}
20+
21+
pub fn to_str(&self) -> Result<&str, Utf8Error> {
22+
self.as_cstr().to_str()
23+
}
24+
}
25+
26+
impl Debug for String {
27+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28+
write!(f, "{:?}", self.as_cstr())
29+
}
30+
}
31+
32+
impl Display for String {
33+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
34+
write!(f, "{}", self.as_cstr().to_string_lossy())
35+
}
36+
}
37+
38+
impl Drop for String {
39+
fn drop(&mut self) {
40+
unsafe { cpp::duckdb_free(self.ptr.cast_mut().cast()) };
41+
}
42+
}

0 commit comments

Comments
 (0)