traefik / yaegi

Yaegi is Another Elegant Go Interpreter
https://pkg.go.dev/github.com/traefik/yaegi
Apache License 2.0
7.02k stars 348 forks source link

segfault while compiling code which initializes slice from struct field #1627

Open runsisi opened 5 months ago

runsisi commented 5 months ago

The following program sample.go triggers an unexpected result

package main

import (
    "fmt"
    "os"
    "reflect"

    "github.com/traefik/yaegi/interp"
)

type Actor struct {
    Age int
}

type Play struct {
    Actors []Actor
}

var Symbols = map[string]map[string]reflect.Value{
    "x/play/play": {
        "Actor": reflect.ValueOf((*Actor)(nil)),
        "Play":  reflect.ValueOf((*Play)(nil)),
    },
}

var code = `
import (
    "x/play"
)

func Action() {
    p := play.Play{}
    ages := []int{p.Actors[0].Age}
}
`

func main() {
    vm := interp.New(interp.Options{})
    err := vm.Use(Symbols)
    if err != nil {
        fmt.Println("import error: ", err)
        os.Exit(1)
    }
    _, err = vm.Compile(code)
    if err != nil {
        fmt.Println("compile error: ", err)
        os.Exit(2)
    }
}

Expected result

// no output expected

Got

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x128 pc=0x649bb4]

goroutine 1 [running]:
github.com/traefik/yaegi/interp.nodeType2(0xc00014c008, 0xc000138240, 0xc0001543c0, {0xc000076118, 0x0, 0x1})
        /home/runsisi/working/go/yaegi/interp/type.go:978 +0x2594
github.com/traefik/yaegi/interp.nodeType(...)
        /home/runsisi/working/go/yaegi/interp/type.go:400
github.com/traefik/yaegi/interp.(*Interpreter).cfg.func1(0xc000154000)
        /home/runsisi/working/go/yaegi/interp/cfg.go:414 +0x3e47
github.com/traefik/yaegi/interp.(*node).Walk(0xc000154000, 0xc0000a7cf8, 0xc0000a7ca0)
        /home/runsisi/working/go/yaegi/interp/interp.go:282 +0x2e
github.com/traefik/yaegi/interp.(*node).Walk(0xc000151cc0, 0xc0000a7cf8, 0xc0000a7ca0)
        /home/runsisi/working/go/yaegi/interp/interp.go:286 +0x6b
github.com/traefik/yaegi/interp.(*node).Walk(0xc000151400, 0xc0000a7cf8, 0xc0000a7ca0)
        /home/runsisi/working/go/yaegi/interp/interp.go:286 +0x6b
github.com/traefik/yaegi/interp.(*node).Walk(0xc000150c80, 0xc0000a7cf8, 0xc0000a7ca0)
        /home/runsisi/working/go/yaegi/interp/interp.go:286 +0x6b
github.com/traefik/yaegi/interp.(*node).Walk(0xc000150640, 0xc0000a7cf8, 0xc0000a7ca0)
        /home/runsisi/working/go/yaegi/interp/interp.go:286 +0x6b
github.com/traefik/yaegi/interp.(*Interpreter).cfg(0xc00014c008, 0xc000150640, 0xc000138240, {0xc000012410, 0x4}, {0xc000012410, 0x4})
        /home/runsisi/working/go/yaegi/interp/cfg.go:69 +0x29a
github.com/traefik/yaegi/interp.(*Interpreter).CompileAST(0xc00014c008, {0x73f5b0?, 0xc000034320?})
        /home/runsisi/working/go/yaegi/interp/program.go:97 +0x14d
github.com/traefik/yaegi/interp.(*Interpreter).compileSrc(0xc00014c008, {0x6e9e47?, 0x0?}, {0x0?, 0x0?}, 0x0?)
        /home/runsisi/working/go/yaegi/interp/program.go:64 +0xaa
github.com/traefik/yaegi/interp.(*Interpreter).Compile(...)
        /home/runsisi/working/go/yaegi/interp/program.go:33
main.main()
        /home/runsisi/working/test/go/work/xp.go:44 +0xea
exit status 2

Yaegi Version

c828692c0b

Additional Notes

No response

runsisi commented 5 months ago

the patch below fixes the segfault, but i am not sure if it's the right fix.

diff --git a/interp/type.go b/interp/type.go
index b322045..b533636 100644
--- a/interp/type.go
+++ b/interp/type.go
@@ -829,6 +829,8 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
                switch lt.cat {
                case arrayT, mapT, sliceT, variadicT:
                        t = lt.val
+               case valueT:
+                       t = valueTOf(lt.rtype.Elem())
                case genericT:
                        t1, err := nodeType2(interp, sc, n.child[1], seen)
                        if err != nil {