Skip to content

Commit d1e6967

Browse files
committed
fix(vm): handle nil arguments in variadic funcs
Update OpCall to properly handle nil values passed to variadic functions. Previously, passing nil as the last argument caused an index out of range panic, and a single nil argument was incorrectly treated as a nil slice. Added regression tests. Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
1 parent ad49544 commit d1e6967

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

test/issues/817/issue_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package issue_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/expr-lang/expr"
8+
"github.com/expr-lang/expr/internal/testify/require"
9+
)
10+
11+
func TestIssue817_1(t *testing.T) {
12+
out, err := expr.Eval(
13+
`sprintf("result: %v %v", 1, nil)`,
14+
map[string]any{
15+
"sprintf": fmt.Sprintf,
16+
},
17+
)
18+
require.NoError(t, err)
19+
require.Equal(t, "result: 1 <nil>", out)
20+
}
21+
22+
func TestIssue817_2(t *testing.T) {
23+
out, err := expr.Eval(
24+
`thing(nil)`,
25+
map[string]any{
26+
"thing": func(arg ...any) string {
27+
return fmt.Sprintf("result: (%T) %v", arg[0], arg[0])
28+
},
29+
},
30+
)
31+
require.NoError(t, err)
32+
require.Equal(t, "result: (<nil>) <nil>", out)
33+
}

vm/vm.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,21 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
331331

332332
case OpCall:
333333
fn := reflect.ValueOf(vm.pop())
334+
fnType := fn.Type()
334335
size := arg
335336
in := make([]reflect.Value, size)
337+
isVariadic := fnType.IsVariadic()
338+
numIn := fnType.NumIn()
336339
for i := int(size) - 1; i >= 0; i-- {
337340
param := vm.pop()
338341
if param == nil {
339-
in[i] = reflect.Zero(fn.Type().In(i))
342+
var inType reflect.Type
343+
if isVariadic && i >= numIn-1 {
344+
inType = fnType.In(numIn - 1).Elem()
345+
} else {
346+
inType = fnType.In(i)
347+
}
348+
in[i] = reflect.Zero(inType)
340349
} else {
341350
in[i] = reflect.ValueOf(param)
342351
}

0 commit comments

Comments
 (0)