Skip to content
This repository has been archived by the owner on May 11, 2020. It is now read-only.

Commit

Permalink
exec: fix div instruction
Browse files Browse the repository at this point in the history
* exec: fix div instruction
* exec: fix out of bound check overflow
* fix memory grow check
  • Loading branch information
laizy authored Mar 13, 2020
1 parent 6803234 commit dc6758c
Show file tree
Hide file tree
Showing 14 changed files with 332 additions and 21 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "tests/spectestcase"]
path = tests/spectestcase
url = https://github.com/ontio/testsuite
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ script:
- GOARCH=386 go install -v $TAGS ./...
- GOARCH=amd64 go install -v $TAGS ./...
- go run ./ci/run-tests.go $COVERAGE
- cd tests && bash ./run_testcase.sh

after_success:
- bash <(curl -s https://codecov.io/bash)
12 changes: 10 additions & 2 deletions exec/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

package exec

import "errors"
import (
"errors"

"github.com/go-interpreter/wagon/wasm"
)

var (
// ErrSignatureMismatch is the error value used while trapping the VM when
Expand All @@ -31,7 +35,11 @@ func (vm *VM) callIndirect() {
if int(tableIndex) >= len(vm.module.TableIndexSpace[0]) {
panic(ErrUndefinedElementIndex)
}
elemIndex := vm.module.TableIndexSpace[0][tableIndex]
tableEntry := vm.module.TableIndexSpace[0][tableIndex]
if !tableEntry.Initialized {
panic(wasm.UninitializedTableEntryError(tableIndex))
}
elemIndex := tableEntry.Index
fnActual := vm.module.FunctionIndexSpace[elemIndex]

if len(fnExpect.ParamTypes) != len(fnActual.Sig.ParamTypes) {
Expand Down
17 changes: 13 additions & 4 deletions exec/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ func (vm *VM) fetchBaseAddr() int {

// inBounds returns true when the next vm.fetchBaseAddr() + offset
// indices are in bounds accesses to the linear memory.
func (vm *VM) inBounds(offset int) bool {
addr := endianess.Uint32(vm.ctx.code[vm.ctx.pc:]) + uint32(vm.ctx.stack[len(vm.ctx.stack)-1])
return int(addr)+offset < len(vm.memory)
func (vm *VM) inBounds(offset uint32) bool {
addr := uint64(endianess.Uint32(vm.ctx.code[vm.ctx.pc:])) + uint64(uint32(vm.ctx.stack[len(vm.ctx.stack)-1]))
return addr+uint64(offset) < uint64(len(vm.memory))
}

// curMem returns a slice to the memory segment pointed to by
Expand Down Expand Up @@ -208,7 +208,16 @@ func (vm *VM) currentMemory() {
func (vm *VM) growMemory() {
_ = vm.fetchInt8() // reserved (https://github.com/WebAssembly/design/blob/27ac254c854994103c24834a994be16f74f54186/BinaryEncoding.md#memory-related-operators-described-here)
curLen := len(vm.memory) / wasmPageSize
n := vm.popInt32()
n := vm.popUint32()

maxMem := vm.module.Memory.Entries[0].Limits.Maximum
newPage := uint64(n + uint32(len(vm.memory)/wasmPageSize))

if newPage > 1<<16 || newPage > uint64(maxMem) {
vm.pushInt32(-1)
return
}

vm.memory = append(vm.memory, make([]byte, n*wasmPageSize)...)
vm.pushInt32(int32(curLen))
}
19 changes: 13 additions & 6 deletions exec/num.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package exec

import (
"errors"
"math"
"math/bits"
)
Expand Down Expand Up @@ -34,6 +35,9 @@ func (vm *VM) i32Mul() {
func (vm *VM) i32DivS() {
v2 := vm.popInt32()
v1 := vm.popInt32()
if v1 == math.MinInt32 && v2 == -1 {
panic(errors.New("integer overflow"))
}
vm.pushInt32(v1 / v2)
}

Expand Down Expand Up @@ -76,19 +80,19 @@ func (vm *VM) i32Xor() {
func (vm *VM) i32Shl() {
v2 := vm.popUint32()
v1 := vm.popUint32()
vm.pushUint32(v1 << v2)
vm.pushUint32(v1 << (v2 % 32))
}

func (vm *VM) i32ShrU() {
v2 := vm.popUint32()
v1 := vm.popUint32()
vm.pushUint32(v1 >> v2)
vm.pushUint32(v1 >> (v2 % 32))
}

func (vm *VM) i32ShrS() {
v2 := vm.popUint32()
v1 := vm.popInt32()
vm.pushInt32(v1 >> v2)
vm.pushInt32(v1 >> (v2 % 32))
}

func (vm *VM) i32Rotl() {
Expand Down Expand Up @@ -194,6 +198,9 @@ func (vm *VM) i64Mul() {
func (vm *VM) i64DivS() {
v2 := vm.popInt64()
v1 := vm.popInt64()
if v1 == math.MinInt64 && v2 == -1 {
panic(errors.New("integer overflow"))
}
vm.pushInt64(v1 / v2)
}

Expand Down Expand Up @@ -230,19 +237,19 @@ func (vm *VM) i64Xor() {
func (vm *VM) i64Shl() {
v2 := vm.popUint64()
v1 := vm.popUint64()
vm.pushUint64(v1 << v2)
vm.pushUint64(v1 << (v2 % 64))
}

func (vm *VM) i64ShrS() {
v2 := vm.popUint64()
v1 := vm.popInt64()
vm.pushInt64(v1 >> v2)
vm.pushInt64(v1 >> (v2 % 64))
}

func (vm *VM) i64ShrU() {
v2 := vm.popUint64()
v1 := vm.popUint64()
vm.pushUint64(v1 >> v2)
vm.pushUint64(v1 >> (v2 % 64))
}

func (vm *VM) i64Rotl() {
Expand Down
20 changes: 20 additions & 0 deletions exec/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,26 @@ func (vm *VM) Memory() []byte {
return vm.memory
}

// GetExportEntry returns ExportEntry of this VM's Wasm module.
func (vm *VM) GetExportEntry(name string) (wasm.ExportEntry, bool) {
entry, ok := vm.module.Export.Entries[name]
return entry, ok
}

// GetGlobal returns the global value represented as uint64 defined in this VM's Wasm module.
func (vm *VM) GetGlobal(name string) (uint64, bool) {
entry, ok := vm.GetExportEntry(name)
if !ok {
return 0, false
}
index := entry.Index
if int64(index) >= int64(len(vm.globals)) {
return 0, false
}

return vm.globals[index], true
}

func (vm *VM) pushBool(v bool) {
if v {
vm.pushUint64(1)
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ require (
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc
golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e // indirect
)

// users in some countries cannot access golang.org.
replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190306220234-b354f8bf4d9e
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/golang/sys v0.0.0-20190306220234-b354f8bf4d9e h1:Yv9Nf3qPhnbsludlsbTa1z6lOpYbJxHKoh5lXyqfP3I=
github.com/golang/sys v0.0.0-20190306220234-b354f8bf4d9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc h1:RTUQlKzoZZVG3umWNzOYeFecQLIh+dbxXvJp1zPQJTI=
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc/go.mod h1:NoCfSFWosfqMqmmD7hApkirIK9ozpHjxRnRxs1l413A=
golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e h1:UndnRDGP/JcdZX1LBubo1fJ3Jt6GnKREteLJvysiiPE=
golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
25 changes: 25 additions & 0 deletions tests/run_testcase.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

set -ex
rm -rf temp
mkdir temp
cd temp

if ! which wast2json ; then
wget https://github.com/WebAssembly/wabt/releases/download/1.0.13/wabt-1.0.13-linux.tar.gz
tar -xzvf wabt-1.0.13-linux.tar.gz
WAST2JSON=wabt-1.0.13/wast2json
else
WAST2JSON=wast2json
fi


go build $TAGS -o spec_test ../spec_test_runner.go

for file in ../spectestcase/*.wast ; do
${WAST2JSON} ${file}
done

for json in *.json ; do
./spec_test ${json}
done
Loading

0 comments on commit dc6758c

Please sign in to comment.