perlin-network / life

A secure WebAssembly VM catered for decentralized applications.
MIT License
1.7k stars 119 forks source link

User-friendly Fix: Need to panic that DefaultMemoryPages config option should be 1 or more #111

Open mallochine opened 3 years ago

mallochine commented 3 years ago

EDIT: please see my last comment on this issue for how I managed to fix the error I reported below.


FYI I raised the same issue with gasm (https://github.com/mathetake/gasm/issues/18). They have the same problem. I copy-pasted a lot of it since a lot of it is the same.

Here is a repro test case for ya:

package main

import (
  "io/ioutil"
  "testing"
  "github.com/perlin-network/life/exec"
)

// Taken from the example
// https://github.com/perlin-network/life#executing-webassembly-modules
func Test_Life(t *testing.T) {
  // Note that I tested this with a basic example "wasm/fibonacci.wasm" and
  // I can confirm this works. So the error is not with this repro example
  // but with something that this VM can't support somehow.
  // bytes, err := ioutil.ReadFile("wasm/bls.wasm")

  // Read WebAssembly *.wasm file.
  bytes, err := ioutil.ReadFile("wasm/bls.wasm")
  if err != nil {
    panic(err)
  }
  _, err = exec.NewVirtualMachine(bytes, exec.VMConfig{}, new(exec.NopResolver), nil)
  if err != nil {
    panic(err)
  }
}

And I've attached the bls.wasm file as a bls.txt since Github won't let me upload a filetype wasm.

bls.txt

There are other two ways of getting the wasm:

  1. download the bls.wasm file by going to https://herumi.github.io/bls-wasm/browser/demo.html , open Network tab in Chrome Developer Console, then download the file in data:application/octet-stream.
  2. Go to the repo file: https://github.com/herumi/bls-wasm/blob/master/src/bls_c.js#L403 and download that long line on line 403. That's base64. Write a little Golang to decode the base64 string to a buffer and you'll have the exact same thing.

This is the error message I get

p$ go test
panic: Error: runtime error: slice bounds out of range [1024:0]
---GO TRACEBACK---
goroutine 20 [running]:
runtime/debug.Stack(0x87ae80, 0xc000016280, 0x7fdc84401860)
        /usr/lib/go-1.13/src/runtime/debug/stack.go:24 +0x9d
github.com/perlin-network/life/utils.CatchPanic(0xc000161f50)
        ./p/go/src/github.com/perlin-network/life/utils/catch.go:11 +0x72
panic(0x87ae80, 0xc000016280)
        /usr/lib/go-1.13/src/runtime/panic.go:679 +0x1b2
github.com/perlin-network/life/exec.NewVirtualMachine(0xc000110000, 0x6053b, 0x6073b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        ./p/go/src/github.com/perlin-network/life/exec/vm.go:537 +0x12a5
./p.Test_Life(0xc0000b8200)
        ./p/life_test.go:22 +0xe7
testing.tRunner(0xc0000b8200, 0x8c6968)
        /usr/lib/go-1.13/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
        /usr/lib/go-1.13/src/testing/testing.go:960 +0x350
 [recovered]
        panic: Error: runtime error: slice bounds out of range [1024:0]
---GO TRACEBACK---
goroutine 20 [running]:
runtime/debug.Stack(0x87ae80, 0xc000016280, 0x7fdc84401860)
        /usr/lib/go-1.13/src/runtime/debug/stack.go:24 +0x9d
github.com/perlin-network/life/utils.CatchPanic(0xc000161f50)
        ./p/go/src/github.com/perlin-network/life/utils/catch.go:11 +0x72
panic(0x87ae80, 0xc000016280)
        /usr/lib/go-1.13/src/runtime/panic.go:679 +0x1b2
github.com/perlin-network/life/exec.NewVirtualMachine(0xc000110000, 0x6053b, 0x6073b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        ./p/go/src/github.com/perlin-network/life/exec/vm.go:537 +0x12a5
./p.Test_Life(0xc0000b8200)
        ./p/life_test.go:22 +0xe7
testing.tRunner(0xc0000b8200, 0x8c6968)
        /usr/lib/go-1.13/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
        /usr/lib/go-1.13/src/testing/testing.go:960 +0x350

goroutine 20 [running]:
testing.tRunner.func1(0xc0000b8200)
        /usr/lib/go-1.13/src/testing/testing.go:874 +0x3a3
panic(0x830120, 0xc0001ccd40)
        /usr/lib/go-1.13/src/runtime/panic.go:679 +0x1b2
./p.Test_Life(0xc0000b8200)
        ./p/life_test.go:24 +0x120
testing.tRunner(0xc0000b8200, 0x8c6968)
        /usr/lib/go-1.13/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
        /usr/lib/go-1.13/src/testing/testing.go:960 +0x350
exit status 2
FAIL    ./p 0.036s
mallochine commented 3 years ago

hello, ping, any chance this is going to get looked at soon?

mallochine commented 3 years ago

I was going to try to patch the library, but while trying to do it I discovered the way to fix this is to tell the perlin network VM to grow the memory with a new VMConfig:

  _, err = exec.NewVirtualMachine(bytes, exec.VMConfig{
      MaxMemoryPages: 4,
      DefaultMemoryPages: 1,
    }, new(exec.NopResolver), nil)

It was erroring out because of this line: copy(memory[offset:], e.Data) where len(memory) was 0. It was zero due to initialLimit being 0 (initialLimit := int(m.Base.Memory.Entries[0].Limits.Initial))

So the fix for this issue then is to make the perlin-network/life more user friendly by doing this:

if initialLimit == 0 {
  panic("Please configure MaxMemoryPages and DefaultMemoryPages to be more than 0 so that PerlinNetwork Life can grow the Webassembly VM memory")
}

Can somebody submit a pull request for this? I'm busy right now with other stuff, thanks!