Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsoniter stack overflow #1431

Closed
charles-d-burton opened this issue Jul 29, 2022 · 2 comments · Fixed by #1432
Closed

jsoniter stack overflow #1431

charles-d-burton opened this issue Jul 29, 2022 · 2 comments · Fixed by #1432
Labels
area/core bug Something isn't working

Comments

@charles-d-burton
Copy link

The following program sample.go triggers an unexpected result

package main

import (
	"fmt"
	"os"

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

func main() {
	fmt.Println("loading source file")

	/*zipfile := "./source.zip"

	zf, err := zip.OpenReader(zipfile)
	if err != nil {
		fmt.Println(err)
	}*/
	zf := os.DirFS("./source")

	fmt.Println("generating options")
	options := interp.Options{
		//		GoPath:               "/home/charles/Development/ziploader/loader/source",
		SourcecodeFilesystem: zf,
		//SourcecodeFilesystem: &zf.Reader,
	}

	fmt.Println("loading interp")
	i := interp.New(options)

	fmt.Println("loading stdlb")
	if err := i.Use(stdlib.Symbols); err != nil {
		fmt.Println(err)
	}

	if err := i.Use(interp.Symbols); err != nil {
		fmt.Println(err)
	}

	if err := i.Use(unsafe.Symbols); err != nil {
		fmt.Println(err)
	}

	fmt.Println("evaluating source")
	_, err := i.EvalPath(`./`)
	if err != nil {
		fmt.Println(err)
	}
}

Expected result

go run ./main.go
{"hello":"world"}

Got

loading source file
generating options
loading interp
loading stdlb
evaluating source
runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc023700410 stack=[0xc023700000, 0xc043700000]
fatal error: stack overflow

runtime stack:
runtime.throw({0xdfae79?, 0x1432860?})
	/usr/lib/go-1.18/src/runtime/panic.go:992 +0x71
runtime.newstack()
	/usr/lib/go-1.18/src/runtime/stack.go:1101 +0x5cc
runtime.morestack()
	/usr/lib/go-1.18/src/runtime/asm_amd64.s:547 +0x8b

goroutine 1 [running]:
runtime.heapBitsSetType(0xc006459040?, 0xd0?, 0xc8?, 0xd9df80?)
	/usr/lib/go-1.18/src/runtime/mbitmap.go:832 +0xbcc fp=0xc023700420 sp=0xc023700418 pc=0x41a9ec
runtime.mallocgc(0xc8, 0xd9df80, 0x1)
	/usr/lib/go-1.18/src/runtime/malloc.go:1117 +0x673 fp=0xc023700498 sp=0xc023700420 pc=0x411fd3
runtime.newobject(0xc023700520?)
	/usr/lib/go-1.18/src/runtime/malloc.go:1259 +0x27 fp=0xc0237004c0 sp=0xc023700498 pc=0x412387
os.statNolog({0xc000150630, 0x2f})
	/usr/lib/go-1.18/src/os/stat_unix.go:30 +0x2e fp=0xc023700510 sp=0xc0237004c0 pc=0x5026ae
os.Stat({0xc000150630, 0x2f})
	/usr/lib/go-1.18/src/os/stat.go:13 +0x34 fp=0xc023700530 sp=0xc023700510 pc=0x502214
os.dirFS.Stat({0xdf0026, 0x8}, {0xc000150600, 0x26})
	/usr/lib/go-1.18/src/os/file.go:658 +0x6a fp=0xc023700578 sp=0xc023700530 pc=0x4fd6aa
os.(*dirFS).Stat(0x0?, {0xc000150600?, 0xc000114110?})
	<autogenerated>:1 +0x3f fp=0xc0237005a8 sp=0xc023700578 pc=0x50427f
io/fs.Stat({0xfb9720, 0xc000114110}, {0xc000150600, 0x26})
	/usr/lib/go-1.18/src/io/fs/stat.go:22 +0x167 fp=0xc023700628 sp=0xc0237005a8 pc=0x4eabc7
github.com/traefik/yaegi/interp.(*Interpreter).pkgDir(0xc00033a000, {0x0, 0x0}, {0xfb4118, 0x1}, {0xc0002a2061, 0x1b})
	/home/charles/Development/go/pkg/mod/github.com/traefik/yaegi@v0.13.0/interp/src.go:200 +0x18c fp=0xc023700770 sp=0xc023700628 pc=0x6c264c
github.com/traefik/yaegi/interp.(*Interpreter).pkgDir(0xc00033a000, {0x0, 0x0}, {0xfb4118, 0x1}, {0xc0002a2061, 0x1b})
	/home/charles/Development/go/pkg/mod/github.com/traefik/yaegi@v0.13.0/interp/src.go:223 +0x489 fp=0xc0237008b8 sp=0xc023700770 pc=0x6c2949
github.com/traefik/yaegi/interp.(*Interpreter).pkgDir(0xc00033a000, {0x0, 0x0}, {0xfb4118, 0x1}, {0xc0002a2061, 0x1b})
	/home/charles/Development/go/pkg/mod/github.com/traefik/yaegi@v0.13.0/interp/src.go:223 +0x489 fp=0xc023700a00 sp=0xc0237008b8 pc=0x6c2949
github.com/traefik/yaegi/interp.(*Interpreter).pkgDir(0xc00033a000, {0x0, 0x0}, {0xfb4118, 0x1}, {0xc0002a2061, 0x1b})
	/home/charles/Development/go/pkg/mod/github.com/traefik/yaegi@v0.13.0/interp/src.go:223 +0x489 fp=0xc023700b48 sp=0xc023700a00 pc=0x6c2949
github.com/traefik/yaegi/interp.(*Interpreter).pkgDir(0xc00033a000, {0x0, 0x0}, {0xfb4118, 0x1}, {0xc0002a2061, 0x1b})
	/home/charles/Development/go/pkg/mod/github.com/traefik/yaegi@v0.13.0/interp/src.go:223 +0x489 fp=0xc023700c90 sp=0xc023700b48 pc=0x6c2949
github.com/traefik/yaegi/interp.(*Interpreter).pkgDir(0xc00033a000, {0x0, 0x0}, {0xfb4118, 0x1}, {0xc0002a2061, 0x1b})
	/home/charles/Development/go/pkg/mod/github.com/traefik/yaegi@v0.13.0/interp/src.go:223 +0x489 fp=0xc023700dd8 sp=0xc023700c90 pc=0x6c2949

Yaegi Version

v0.13.0

Additional Notes

Put the following code in a directory named source and run

go mod vendor
package main

import (
	"log"

	jsoniter "github.com/json-iterator/go"
)

var (
	json = jsoniter.ConfigCompatibleWithStandardLibrary
)

type Test struct {
	Hello string `json:"hello"`
}

func main() {
	hello := Test{"hello world"}
	data, err := json.Marshal(&hello)
	if err != nil {
		log.Println(err)
	}
	log.Println(string(data))
}
@mvertes mvertes added bug Something isn't working area/core labels Aug 1, 2022
@mvertes mvertes added this to the v0.13.x milestone Aug 1, 2022
@mvertes
Copy link
Member

mvertes commented Aug 1, 2022

A problem here is that in github.com/modern-go/reflect2 dependency package, there is some code which is fundamentally incompatible with yaegi, using some "//go:linkname" pragma to link to internal (unexported) stdlib symbols during compilation.

For ex. in https://github.com/modern-go/reflect2/blob/master/go_below_118.go line 12:

//go:linkname mapiterinit reflect.mapiterinit
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) (val *hiter)

There is no way yaegi (or another interpreter) can solve that from the pre-compiled runtime.

Of course yaegi should not panic here and gracefully abort those pathological cases. This is what I will fix, but unfortunately it will not make your code work.

mvertes added a commit to mvertes/yaegi that referenced this issue Aug 1, 2022
Such function declaration denotes either a linkname (an access to
an arbitrary, typically unexported symbol, solved by go compiler),
or a foreign C or assembly implementation of the body.

Those cases are not supported (or planned to be) by the interpreter.

Fixes traefik#1431.
@charles-d-burton
Copy link
Author

All good! That makes perfect sense.

@ldez ldez modified the milestones: v0.13.x, v0.14.x Aug 3, 2022
mvertes added a commit to mvertes/yaegi that referenced this issue Aug 3, 2022
Such function declaration denotes either a linkname (an access to
an arbitrary, typically unexported symbol, solved by go compiler),
or a foreign C or assembly implementation of the body.

Those cases are not supported (or planned to be) by the interpreter.

Fixes traefik#1431.
traefiker pushed a commit that referenced this issue Aug 3, 2022
Such function declaration denotes either a linkname (an access to
an arbitrary, typically unexported symbol, solved by go compiler),
or a foreign C or assembly implementation of the body.

Those cases are not supported (or planned to be) by the interpreter.

Fixes #1431.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/core bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants