Skip to content

Commit e79eb40

Browse files
hellowerclaude
andcommitted
fix: same defer-capture leak in destroyValueSlice (3 additional sites)
The same bug pattern exists for destroyValueSlice in value.go: - inferSliceLogicalTypeAndValue (line 398): values := make([]Value, 0, length) - createSliceValue (line 459): var values []Value - createStructValue (line 487): var values []Value All three use `defer destroyValueSlice(values)` where `values` is nil or len=0 at the defer site. The deferred cleanup iterates over zero elements and never calls DestroyValue on the C-allocated duckdb_value objects. These functions are called when binding STRUCT, LIST, or ARRAY values via Appender or prepared statements. Each call leaks one C Value object per element/field. Not a double-free risk: DuckDB's Create*Value functions (CreateListValue, CreateArrayValue, CreateStructValue) deep-copy the input values via allocValues → duckdb_create_*_value. The original Value objects remain owned by the caller and must be destroyed separately. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 62abb76 commit e79eb40

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

value.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ func inferSliceLogicalTypeAndValue[T any](val T, array bool, length int) (mappin
395395
}
396396

397397
values := make([]mapping.Value, 0, length)
398-
defer destroyValueSlice(values)
398+
defer func() { destroyValueSlice(values) }()
399399

400400
if len(slice) == 0 {
401401
lt := mapping.CreateLogicalType(TYPE_SQLNULL)
@@ -456,7 +456,7 @@ func createSliceValue[T any](lt mapping.LogicalType, t Type, val T) (mapping.Val
456456
}
457457

458458
var values []mapping.Value
459-
defer destroyValueSlice(values)
459+
defer func() { destroyValueSlice(values) }()
460460

461461
for _, v := range slice {
462462
vv, err := createValue(childType, v)
@@ -484,7 +484,7 @@ func createStructValue(lt mapping.LogicalType, val any) (mapping.Value, error) {
484484
}
485485

486486
var values []mapping.Value
487-
defer destroyValueSlice(values)
487+
defer func() { destroyValueSlice(values) }()
488488

489489
childCount := mapping.StructTypeChildCount(lt)
490490
for i := range uint64(childCount) {

0 commit comments

Comments
 (0)