Skip to content

interp: mis-interpretation of global map initializer #4505

@eliasnaur

Description

@eliasnaur
Contributor
$ cat precomp.go
package main

import (
	"crypto/sha256"
	"fmt"
	"os"
)

var (
	tag       = sha256.Sum256(nil)
	globalMap = map[string][32]byte{
		"": tag,
	}
)

func main() {
	localMap := map[string][32]byte{
		"": tag,
	}
	if localMap[""] != globalMap[""] {
		fmt.Printf("global %.32x\nlocal %.32x\n", globalMap, localMap)
		os.Exit(1)
	}
}
$ go run precomp.go
$ tinygo run precomp.go
global map[:0000000000000000000000000000000000000000000000000000000000000000]
local map[:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855]
failed to run compiled binary /tmp/nix-shell.HWhNg6/tinygo1488071277/main: exit status 1

This breaks anything relying on https://github.com/btcsuite/btcd/blob/67b8efd3ba53b60ff0eba5d79babe2c3d82f6c54/chaincfg/chainhash/hash.go#L50.

Activity

dgryski

dgryski commented on Oct 7, 2024

@dgryski
Member

Interestingly, switching the runtime hash to tsip allows this code to pass. I wonder if it's because interp decides not to run the tsip code for some reason.

~/go/src/github.com/dgryski/bug/interp $ for hash in fnv leveldb tsip; do echo $hash; tinygo run -tags=runtime_memhash_${hash} main.go; done
fnv
global map[:0000000000000000000000000000000000000000000000000000000000000000]
local map[:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855]
failed to run compiled binary /var/folders/5b/_hr1d1fd3qn4t9vtfx5p61wm0000gp/T/tinygo3541483627/main: exit status 1
leveldb
global map[:0000000000000000000000000000000000000000000000000000000000000000]
local map[:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855]
failed to run compiled binary /var/folders/5b/_hr1d1fd3qn4t9vtfx5p61wm0000gp/T/tinygo1726170860/main: exit status 1
tsip
~/go/src/github.com/dgryski/bug/interp $
eliasnaur

eliasnaur commented on Nov 16, 2024

@eliasnaur
ContributorAuthor

Can you say where to look into a fix, however hacky? This is a miscompilation of an external package that is impractical to change.

dgryski

dgryski commented on Nov 16, 2024

@dgryski
Member

When building with -tags=runtime_memhash_tsip I see the following:

                    load: <2468+4> -> 1819895653
                    call: math/bits.RotateLeft32(1819895653, 5, 0)
                        trunc: 5 32
                        call <1447> <!> <!> <!>
                        ret <!>
                    !! revert because of error: interp: unsupported instruction (to be emitted at runtime)

So now at least we know why switching the hash function works.

dgryski

dgryski commented on Nov 16, 2024

@dgryski
Member

Here's a simpler reproducer:

package main

import (
	"math/bits"
)

func sum(b []byte) byte {
	return bits.RotateLeft8(1, len(b))
}

var (
	tag       = sum([]byte{1})
	globalMap = map[string]byte{
		"": tag,
	}
)

func main() {
	localMap := map[string]byte{
		"": tag,
	}
	if localMap[""] != globalMap[""] {
		println("global", globalMap[""], localMap[""])
		panic("mismatch")
	}

	println("value:", localMap[""])
}

So what's happening here is that sum() function is unable to be interpreted at interp time and so is pushed off to runtime, but we're not holding off the construction of the map that depends on that value.

So while we should probably add the rotate instructions to interp, the underlying issue is that the map initialization doens't seem to be reverted when one of the values used during construction is.

dgryski

dgryski commented on Nov 16, 2024

@dgryski
Member

@niaow @aykevl I haven't done any work debugging interp, so any pointers here would be helpful.

dkegel-fastly

dkegel-fastly commented on Nov 17, 2024

@dkegel-fastly
Contributor

@eliasnaur You could disable interp as a hacky workaround...?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcore

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @deadprogram@eliasnaur@dgryski@dkegel-fastly

        Issue actions

          interp: mis-interpretation of global map initializer · Issue #4505 · tinygo-org/tinygo