hcrosse opened a new issue, #1450:
URL: https://github.com/apache/arrow-go/issues/1450

   ### Describe the bug, including details regarding any error messages, 
version, and platform.
   
   `ExecuteScalarExpression` leaks the referenced column's buffers when a 
top-level field reference has the wrong type. Returning an error leaves an 
extra reference to the column, so releasing the input does not free its buffers.
   
   I reproduced this on main at `22c9f26d` on Linux amd64 and on v18.8.0 on 
macOS arm64. An expression that expects `utf8`, executed on a two-row `int32` 
column, returns `arrow.ErrInvalid` but leaves 128 bytes allocated after the 
input is released.
   
   **Reproduction**
   
   Run it in a module that requires `github.com/apache/arrow-go/v18 v18.8.0`, 
or in a subdirectory of a checkout at `22c9f26d`, with `go run .`:
   
   ```go
   // Leak in exprs.ExecuteScalarExpression when a top-level field reference's
   // type does not match the input column.
   package main
   
   import (
        "context"
        "fmt"
        "strings"
   
        "github.com/apache/arrow-go/v18/arrow"
        "github.com/apache/arrow-go/v18/arrow/array"
        "github.com/apache/arrow-go/v18/arrow/compute"
        "github.com/apache/arrow-go/v18/arrow/compute/exprs"
        "github.com/apache/arrow-go/v18/arrow/memory"
   )
   
   func main() {
        mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
   
        // The expression is built against a schema where "col" is utf8 ...
        exprSchema := arrow.NewSchema([]arrow.Field{{Name: "col", Type: 
arrow.BinaryTypes.String, Nullable: true}}, nil)
        // ... but executed against data where "col" is int32.
        dataSchema := arrow.NewSchema([]arrow.Field{{Name: "col", Type: 
arrow.PrimitiveTypes.Int32, Nullable: true}}, nil)
   
        rec, _, err := array.RecordFromJSON(mem, dataSchema, 
strings.NewReader(`[{"col": 1}, {"col": 2}]`))
        if err != nil {
                panic(err)
        }
   
        bldr := exprs.NewExprBuilder(exprs.NewDefaultExtensionSet())
        if err := bldr.SetInputSchema(exprSchema); err != nil {
                panic(err)
        }
        e, err := bldr.FieldRef("col").BuildExpr()
        if err != nil {
                panic(err)
        }
   
        ctx := compute.WithAllocator(context.Background(), mem)
        result, err := exprs.ExecuteScalarExpression(ctx, dataSchema, e, 
compute.NewDatumWithoutOwning(rec))
        fmt.Printf("result=%v err=%v\n", result, err)
        if result != nil {
                result.Release()
        }
   
        rec.Release()
        fmt.Printf("bytes still allocated after releasing everything: %d\n", 
mem.CurrentAlloc())
   }
   ```
   
   The final line on main is:
   
   ```text
   bytes still allocated after releasing everything: 128
   ```
   
   **Expected behavior**
   
   The type mismatch should still return `arrow.ErrInvalid`, but the allocator 
should report zero bytes after the input is released. With a patch that retains 
the column only after the type check, the same program reports zero.
   
   **Cause**
   
   `execFieldRef` retains the column through `compute.NewDatum(param)` before 
checking its type:
   
   
https://github.com/apache/arrow-go/blob/22c9f26df0abbc2066f5d9ae45f31720d29a4300/arrow/compute/exprs/exec.go#L518-L536
   
   When the check fails, it returns without releasing that datum. This affects 
any top-level column type mismatch that reaches this error branch, not only 
`int32` versus `utf8`. Only the top-level path takes this reference. A nested 
reference returns a value borrowed from its parent, so releasing `out` on the 
error path would release a reference `execFieldRef` does not own. Retaining the 
column only after the type check avoids that.
   
   https://github.com/apache/arrow-go/pull/1449 changes the same type check to 
accept dictionary columns and does not change this reference counting.
   
   I have a patch with tests and can open a PR.
   
   ### Component(s)
   
   Other
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to