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

Freeing quickjs.Runtime after creating a new function causes a segmentation fault. #1

Closed
lithdew opened this issue Jul 9, 2020 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@lithdew
Copy link
Owner

lithdew commented Jul 9, 2020

The suspicion is of possible misuse of JS_NewCFunctionData, which is used over JS_NewCFunction to provide an opaque pointer to proxy() in Go to dispatch Go functions in C.

It may be that this is not the intended use of JS_NewCFunctionData, and that calling JS_FreeRuntime frees unintended memory as a result.

func main() {
	runtime := quickjs.NewRuntime()
	defer runtime.Free()

	ctx := runtime.NewContext()
	defer ctx.Free()

	globals := ctx.Globals()
	defer globals.Free()

	httpFunc := ctx.Function(func(ctx quickjs.Context, this quickjs.Value, args []quickjs.Value) quickjs.Value {
		if len(args) != 1 || !args[0].IsString() {
			return ctx.ThrowTypeError("http(request: string)")
		}

		request := args[0]
		fmt.Println(request.String())

		return request
	})
	defer httpFunc.Free()

	globals.Set("http", httpFunc)

	result, err := ctx.Eval(`http('test')`)
	check(err)
	defer result.Free()

	fmt.Println(result)
}
$ CGO_CFLAGS="-DDUMP_LEAKS" go run main.go
# command-line-arguments
/tmp/go-link-072279044/000024.o: In function `_cgo_26061493d47f_C2func_getaddrinfo':
cgo_unix.cgo2.c:(.text+0x81): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
test
test
main: quickjs.c:5625: gc_decref_child: Assertion `p->ref_count > 0' failed.
SIGABRT: abort
PC=0x782978 m=0 sigcode=18446744073709551610

goroutine 0 [idle]:
runtime: unknown pc 0x782978
stack: frame={sp:0x7ffd922906b8, fp:0x0} stack=[0x7ffd91a91ae8,0x7ffd92290b10)
00007ffd922905b8:  000000000092db5c  0000000000000000 
00007ffd922905c8:  0000000000798780  00000000fbad8000 
00007ffd922905d8:  00000000022c1a00  00000000022c1a00 
00007ffd922905e8:  00000000022c1a00  00000000022c1a00 
00007ffd922905f8:  00000000022c1a4c  00000000022c1a64 
00007ffd92290608:  00000000022c1a00  00000000022c1a64 
00007ffd92290618:  0000000000000000  0000000000000000 
00007ffd92290628:  0000000000000000  0000000000000000 
00007ffd92290638:  0000000000000000  0000000092290660 
00007ffd92290648:  0000000000688a26  00000000022c0000 
00007ffd92290658:  0000000000000000  00007ffd92290690 
00007ffd92290668:  0000000000688aae  ffffffffffffffff 
00007ffd92290678:  0000000000000000  00000000022b70c8 
00007ffd92290688:  00007f356e578000  00000000009b2420 
00007ffd92290698:  000000000092d5c4  00000000000015f9 
00007ffd922906a8:  000000000092db5c  0000000000000000 
00007ffd922906b8: <0000000000782d0a  0000000000000020 
00007ffd922906c8:  0000000000000000  0000000000000000 
00007ffd922906d8:  0000000000000000  0000000000000000 
00007ffd922906e8:  0000000000000000  0000000000000000 
00007ffd922906f8:  0000000000000000  0000000000000000 
00007ffd92290708:  0000000000000000  0000000000000000 
00007ffd92290718:  0000000000000000  0000000000000000 
00007ffd92290728:  0000000000000000  0000000000000000 
00007ffd92290738:  0000000000000000  0000000000000004 
00007ffd92290748:  00000000022b7ab0  00007ffd92290720 
00007ffd92290758:  00000016022c9230  0000000000000000 
00007ffd92290768:  00007f356e578000  00000000009b2420 
00007ffd92290778:  000000000092d5c4  00000000000015f9 
00007ffd92290788:  000000000092db5c  0000000000000000 
00007ffd92290798:  00000000007a5377  00000000022c3bf0 
00007ffd922907a8:  fffffffffffffff9  00000000009c9e9c 
runtime: unknown pc 0x782978
stack: frame={sp:0x7ffd922906b8, fp:0x0} stack=[0x7ffd91a91ae8,0x7ffd92290b10)
00007ffd922905b8:  000000000092db5c  0000000000000000 
00007ffd922905c8:  0000000000798780  00000000fbad8000 
00007ffd922905d8:  00000000022c1a00  00000000022c1a00 
00007ffd922905e8:  00000000022c1a00  00000000022c1a00 
00007ffd922905f8:  00000000022c1a4c  00000000022c1a64 
00007ffd92290608:  00000000022c1a00  00000000022c1a64 
00007ffd92290618:  0000000000000000  0000000000000000 
00007ffd92290628:  0000000000000000  0000000000000000 
00007ffd92290638:  0000000000000000  0000000092290660 
00007ffd92290648:  0000000000688a26  00000000022c0000 
00007ffd92290658:  0000000000000000  00007ffd92290690 
00007ffd92290668:  0000000000688aae  ffffffffffffffff 
00007ffd92290678:  0000000000000000  00000000022b70c8 
00007ffd92290688:  00007f356e578000  00000000009b2420 
00007ffd92290698:  000000000092d5c4  00000000000015f9 
00007ffd922906a8:  000000000092db5c  0000000000000000 
00007ffd922906b8: <0000000000782d0a  0000000000000020 
00007ffd922906c8:  0000000000000000  0000000000000000 
00007ffd922906d8:  0000000000000000  0000000000000000 
00007ffd922906e8:  0000000000000000  0000000000000000 
00007ffd922906f8:  0000000000000000  0000000000000000 
00007ffd92290708:  0000000000000000  0000000000000000 
00007ffd92290718:  0000000000000000  0000000000000000 
00007ffd92290728:  0000000000000000  0000000000000000 
00007ffd92290738:  0000000000000000  0000000000000004 
00007ffd92290748:  00000000022b7ab0  00007ffd92290720 
00007ffd92290758:  00000016022c9230  0000000000000000 
00007ffd92290768:  00007f356e578000  00000000009b2420 
00007ffd92290778:  000000000092d5c4  00000000000015f9 
00007ffd92290788:  000000000092db5c  0000000000000000 
00007ffd92290798:  00000000007a5377  00000000022c3bf0 
00007ffd922907a8:  fffffffffffffff9  00000000009c9e9c 

goroutine 1 [syscall]:
runtime.cgocall(0x6578e2, 0xc000059db0, 0x1f9)
        /snap/go/current/src/runtime/cgocall.go:133 +0x5b fp=0xc000059d80 sp=0xc000059d48 pc=0x403fab
github.com/lithdew/quickjs._Cfunc_JS_FreeRuntime(0x22b7030)
        _cgo_gotypes.go:260 +0x41 fp=0xc000059db0 sp=0xc000059d80 pc=0x504551
github.com/lithdew/quickjs.Runtime.Free.func1(0x22b7030)
        /home/kenta/lithdew/quickjs/quickjs.go:33 +0x4d fp=0xc000059de0 sp=0xc000059db0 pc=0x50691d
github.com/lithdew/quickjs.Runtime.Free(0x22b7030)
        /home/kenta/lithdew/quickjs/quickjs.go:33 +0x2b fp=0xc000059df8 sp=0xc000059de0 pc=0x50556b
main.main()
        /home/kenta/lithdew/ghost/main.go:109 +0x40e fp=0xc000059f88 sp=0xc000059df8 pc=0x656d2e
runtime.main()
        /snap/go/current/src/runtime/proc.go:203 +0x1fa fp=0xc000059fe0 sp=0xc000059f88 pc=0x4359fa
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000059fe8 sp=0xc000059fe0 pc=0x4620d1

rax    0x0
rbx    0x7f356e578000
rcx    0x782978
rdx    0x6
rdi    0x6960
rsi    0x6960
rbp    0x9b2420
rsp    0x7ffd922906b8
r8     0x22c1a00
r9     0x0
r10    0x8
r11    0x206
r12    0x92d5c4
r13    0x15f9
r14    0x92db5c
r15    0x0
rip    0x782978
rflags 0x206
cs     0x33
fs     0x0
gs     0x0
exit status 2
func main() {
	runtime := quickjs.NewRuntime()
	defer runtime.Free()

	ctx := runtime.NewContext()
	defer ctx.Free()

	globals := ctx.Globals()
	defer globals.Free()

	httpFunc := ctx.Function(func(ctx quickjs.Context, this quickjs.Value, args []quickjs.Value) quickjs.Value {
		if len(args) != 1 || !args[0].IsString() {
			return ctx.ThrowTypeError("http(request: string)")
		}

		request := args[0]
		fmt.Println(request.String())

		return request
	})
	//defer httpFunc.Free()

	globals.Set("http", httpFunc)

	result, err := ctx.Eval(`http('test')`)
	check(err)
	//defer result.Free()

	fmt.Println(result)
}
$ CGO_CFLAGS="-DDUMP_LEAKS" go run main.go
# command-line-arguments
/tmp/go-link-896294616/000024.o: In function `_cgo_26061493d47f_C2func_getaddrinfo':
cgo_unix.cgo2.c:(.text+0x81): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
test
test
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x2 addr=0x1e4c030 pc=0x1e4c030]

runtime stack:
runtime.throw(0x8bd124, 0x2a)
        /snap/go/current/src/runtime/panic.go:1116 +0x72
runtime.sigpanic()
        /snap/go/current/src/runtime/signal_unix.go:679 +0x46a

goroutine 1 [syscall]:
runtime.cgocall(0x6577e2, 0xc000059e08, 0x1f9)
        /snap/go/current/src/runtime/cgocall.go:133 +0x5b fp=0xc000059dd8 sp=0xc000059da0 pc=0x403fab
github.com/lithdew/quickjs._Cfunc_JS_FreeRuntime(0x1e38010)
        _cgo_gotypes.go:260 +0x41 fp=0xc000059e08 sp=0xc000059dd8 pc=0x504551
github.com/lithdew/quickjs.Runtime.Free.func1(0x1e38010)
        /home/kenta/lithdew/quickjs/quickjs.go:33 +0x4d fp=0xc000059e38 sp=0xc000059e08 pc=0x50691d
github.com/lithdew/quickjs.Runtime.Free(0x1e38010)
        /home/kenta/lithdew/quickjs/quickjs.go:33 +0x2b fp=0xc000059e50 sp=0xc000059e38 pc=0x50556b
main.main()
        /home/kenta/lithdew/ghost/main.go:109 +0x329 fp=0xc000059f88 sp=0xc000059e50 pc=0x656c49
runtime.main()
        /snap/go/current/src/runtime/proc.go:203 +0x1fa fp=0xc000059fe0 sp=0xc000059f88 pc=0x4359fa
runtime.goexit()
        /snap/go/current/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000059fe8 sp=0xc000059fe0 pc=0x4620d1
exit status 2
@lithdew lithdew added the bug Something isn't working label Jul 9, 2020
@lithdew lithdew self-assigned this Jul 9, 2020
@cemremengu
Copy link
Contributor

cemremengu commented Jul 9, 2020

Here is another similar case:

main.go

package main

import (
	"github.com/lithdew/quickjs"
)

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	rt := quickjs.NewRuntime()

	for i := 0; i < 10000; i++ {

		ctx := rt.NewContext()

		defer ctx.Free()

		globals := ctx.Globals()

		globals.Set("B", ctx.Function(SetRedisObject))

		ctx.Eval(`B('test',{a:'c'});`)
	}
}

redis.go

package main

import (
	"github.com/go-redis/redis"
	"github.com/lithdew/quickjs"
)

var rdb = redis.NewClusterClient(&redis.ClusterOptions{
	Addrs: []string{"localhost:7000"},
})

func ValueToMap(v *quickjs.Value) map[string]interface{} {
	if v.IsObject() == false {
		panic("not an object")
	}
	names, err := v.PropertyNames()
	check(err)

	result := map[string]interface{}{}
	for _, name := range names {
		result[name.String()] = v.GetByAtom(name.Atom).String()
	}
	return result
}

func SetRedisObject(ctx quickjs.Context, this quickjs.Value, args []quickjs.Value) quickjs.Value {
	err := rdb.HMSet(args[0].String(), ValueToMap(&args[1])).Err()
	if err != nil {
		panic(err)
	}
	return ctx.Null()
}

produces:

Exception 0xc0000005 0x0 0xffffffffffffffff 0x632bee
PC=0x632bee

runtime: unknown pc 0x632bee
stack: frame={sp:0x101f7f0, fp:0x0} stack=[0x0,0x101fdc0)
000000000101f6f0:  0000000000190000  00007ff8b22bba17
000000000101f700:  0000000028bfaf30  ffffffffffffffff 
000000000101f710:  0000000000000068  0000000028bfaf30
000000000101f720:  0000000028c32980  0000000028bfaf30
000000000101f730:  000000000101f7e0  00000000006d3e79
000000000101f740:  0000000028bfb420  0000000000000025
000000000101f750:  0000000000196028  0000000028bf3830
000000000101f760:  0000000028bfaf30  ffffffffffffffff
000000000101f770:  0000000028bfaf30  ffffffffffffffff
000000000101f780:  000000000101f7b0  0000000000626a2a
000000000101f790:  0000000028bf6cb0  0000001300000000
000000000101f7a0:  0000000000196028  0000000028bfaf30 
000000000101f7b0:  ffffffffffffffff  000000c000149de0
000000000101f7c0:  00000000007d8105  0000000000000000
000000000101f7d0:  0000000000000000  0000000002030000
000000000101f7e0:  000000000101f890  0000000000632bf1
000000000101f7f0: <0000000000197b70  0000000000197b70
000000000101f800:  0000000000632df5  000000000062832a 
000000000101f810:  0000000028bfacf0  ffffffffffffffff
000000000101f820:  000000000101f830  00000000001975c0
000000000101f830:  0000000028bf6c10  00000000006283c3
000000000101f840:  0000000028c39390  0000000000976c00
000000000101f850:  0001010000000001  0000000028bf5760
000000000101f860:  0000000000197b70  0000000028bfacf0
000000000101f870:  0000000028bfaf40  0000000000197bb8
000000000101f880:  000000000101fa40  0000000000976c00
000000000101f890:  000000000101f8e0  0000000000632f07
000000000101f8a0:  0000000000195f80  0000000028bfacf0
000000000101f8b0:  0000000000632df5  000000000062f130 
000000000101f8c0:  00000000edb13dc1  0000000028bfacf0 
000000000101f8d0:  0000000028bfae20  0000000028bfad00
000000000101f8e0:  000000000101f910  0000000000633244
runtime: unknown pc 0x632bee
stack: frame={sp:0x101f7f0, fp:0x0} stack=[0x0,0x101fdc0)
000000000101f6f0:  0000000000190000  00007ff8b22bba17
000000000101f700:  0000000028bfaf30  ffffffffffffffff
000000000101f710:  0000000000000068  0000000028bfaf30
000000000101f720:  0000000028c32980  0000000028bfaf30
000000000101f730:  000000000101f7e0  00000000006d3e79
000000000101f740:  0000000028bfb420  0000000000000025
000000000101f750:  0000000000196028  0000000028bf3830
000000000101f760:  0000000028bfaf30  ffffffffffffffff
000000000101f770:  0000000028bfaf30  ffffffffffffffff
000000000101f780:  000000000101f7b0  0000000000626a2a 
000000000101f790:  0000000028bf6cb0  0000001300000000
000000000101f7a0:  0000000000196028  0000000028bfaf30
000000000101f7b0:  ffffffffffffffff  000000c000149de0
000000000101f7c0:  00000000007d8105  0000000000000000
000000000101f7d0:  0000000000000000  0000000002030000
000000000101f7e0:  000000000101f890  0000000000632bf1
000000000101f7f0: <0000000000197b70  0000000000197b70
000000000101f800:  0000000000632df5  000000000062832a
000000000101f810:  0000000028bfacf0  ffffffffffffffff
000000000101f820:  000000000101f830  00000000001975c0
000000000101f830:  0000000028bf6c10  00000000006283c3
000000000101f840:  0000000028c39390  0000000000976c00
000000000101f850:  0001010000000001  0000000028bf5760
000000000101f860:  0000000000197b70  0000000028bfacf0
000000000101f870:  0000000028bfaf40  0000000000197bb8
000000000101f880:  000000000101fa40  0000000000976c00
000000000101f890:  000000000101f8e0  0000000000632f07 
000000000101f8a0:  0000000000195f80  0000000028bfacf0
000000000101f8b0:  0000000000632df5  000000000062f130
000000000101f8c0:  00000000edb13dc1  0000000028bfacf0
000000000101f8d0:  0000000028bfae20  0000000028bfad00 
000000000101f8e0:  000000000101f910  0000000000633244

goroutine 1 [syscall]:
github.com/lithdew/quickjs._Cfunc_JS_NewContext(0x195f80, 0x0)
        _cgo_gotypes.go:688 +0x51
github.com/lithdew/quickjs.Runtime.NewContext.func1(0x195f80, 0x28bfa5a0)
        C:/Users/cemre.mengu/go/pkg/mod/github.com/lithdew/quickjs@v0.0.0-20200709202529-fb8d8987e9de/quickjs.go:36 +0x54
github.com/lithdew/quickjs.Runtime.NewContext(0x195f80, 0x0, 0x0, 0x0, 0x0)
        C:/Users/cemre.mengu/go/pkg/mod/github.com/lithdew/quickjs@v0.0.0-20200709202529-fb8d8987e9de/quickjs.go:36 +0x43
main.main()
        C:/Users/cemre.mengu/Desktop/quick/main.go:18 +0x74
rax     0x101f810
rbx     0x28bfacf0
rcx     0x195f80
rdi     0xc000149de0
rsi     0xffffffffffffffff
rbp     0x101f890
rsp     0x101f7f0
r8      0x632df5
r9      0x1010000000001
r10     0x0
r11     0x101f7e0
r12     0x7d8105
r13     0x0
r14     0x0
r15     0x2030000
rip     0x632bee
rflags  0x10202
cs      0x33
fs      0x53
gs      0x2b

@lithdew
Copy link
Owner Author

lithdew commented Jul 10, 2020

Fixed by ee6f6e9.

@lithdew lithdew closed this as completed Jul 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants