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

Problem with accessing uint64 variable inside condition in a loop #157

Open
Skird opened this issue May 17, 2024 · 1 comment
Open

Problem with accessing uint64 variable inside condition in a loop #157

Skird opened this issue May 17, 2024 · 1 comment

Comments

@Skird
Copy link

Skird commented May 17, 2024

Hi! I think I found strange bug when trying to Sprintf uint64 variable

Here is minimal repro

package main

import (
	"fmt"

	"github.com/cosmos72/gomacro/fast"
)

var code = `

import (
	"errors"
	"fmt"
	"math/rand"
)

func GetNewBaz(baz uint64) (uint64, error) {
	if baz > 5 {
		return 3, nil
	}
	return baz, errors.New("fail: baz")
}

func Foo() error {
	var baz uint64 = 10
	q := fmt.Sprintf("starting at baz: %d", baz)
	fmt.Println(q)
	for it := 0; it < 2; it++ {
		newBaz, err := GetNewBaz(baz)
		if err != nil {
			fmt.Println("GetNewBaz errored")
			q := fmt.Sprintf("stopping at baz: %d", baz)
			fmt.Println(q)
			break
		} else {
			baz = newBaz
		}
	}
	return nil
}

`

func main() {
	interp := fast.New()
	interp.Eval(code)
	foo := interp.ValueOf("Foo").Interface().(func() error)
	fmt.Println(foo())
}

It panics like that

$ go run main.go
starting at baz: 10
GetNewBaz errored
panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
github.com/cosmos72/gomacro/fast.(*Symbol).intExpr.func59(0xc000051720?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/fast/identifier.go:964 +0x65
github.com/cosmos72/gomacro/fast.funAsX1.func23(0xc000406198?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/fast/util.go:591 +0x17
github.com/cosmos72/gomacro/fast.call_variadic_ret1.func35(0xc000154460)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/fast/call_variadic.go:423 +0x7d
github.com/cosmos72/gomacro/fast.funAsX1.func35(0xc0000517c8?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/fast/util.go:651 +0x17
github.com/cosmos72/gomacro/fast.(*Comp).DeclVar0.func5(0xc000154460)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/fast/declaration.go:536 +0x35
github.com/cosmos72/gomacro/fast.(*Code).Exec.exec.func2(0xc000154000?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/fast/code.go:176 +0x25c
github.com/cosmos72/gomacro/fast.(*Comp).funcGeneric.func2.1({0x236d560, 0x0, 0x0?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/fast/function.go:438 +0xe9
github.com/cosmos72/gomacro/xreflect.MakeFunc.func1({0x236d560, 0x0, 0x0?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20240506194242-2ff796e3da10/xreflect/wrap.go:39 +0xa3
main.main()
        /home/divashchenko/workspace/goplay/main.go:48 +0x5e
exit status 2
  1. It seems to fail on fmt.Sprintf("stopping at baz: %d", baz), but only inside the loop
  2. It does not panic if I change uint64 to uint32 for example
  3. It panics in the same way on REPL too

It seems the line in fast/identifier.go:964 is the culprit
I'm not sure why, but uint64 is treated differently that other types

Hope that helps and thanks again for the cool package! :)

@Skird
Copy link
Author

Skird commented May 17, 2024

Seems like it has nothing to do with Sprintf, just any reference to baz variable in that branch leads to the same error

package main

import (
	"fmt"

	"github.com/cosmos72/gomacro/fast"
)

var code = `
func Foo() error {
	var baz uint64 = 10
	for it := 0; it < 2; it++ {
		var newBaz uint64
		if baz <= 5 {
			println("Going to access baz")
			bbaz := uint32(baz)
			println(bbaz)
			break
		} else {
			baz = 3
		}
	}
	return nil
}
`

func main() {
	interp := fast.New()
	interp.Eval(code)
	foo := interp.ValueOf("Foo").Interface().(func() error)
	fmt.Println(foo())
}

Prints Going to access baz and then panics
If unused variable newBaz is declared outside loop or not decladred at all everything is ok

UPD: even smaller example

@Skird Skird changed the title Problem with Sprintf and uint64 inside the loop Problem with accessing uint64 variable inside condition in a loop May 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant