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

Commit dc6758c

Browse files
authored
exec: fix div instruction
* exec: fix div instruction * exec: fix out of bound check overflow * fix memory grow check
1 parent 6803234 commit dc6758c

14 files changed

+332
-21
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "tests/spectestcase"]
2+
path = tests/spectestcase
3+
url = https://github.com/ontio/testsuite

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ script:
3434
- GOARCH=386 go install -v $TAGS ./...
3535
- GOARCH=amd64 go install -v $TAGS ./...
3636
- go run ./ci/run-tests.go $COVERAGE
37+
- cd tests && bash ./run_testcase.sh
3738

3839
after_success:
3940
- bash <(curl -s https://codecov.io/bash)

exec/call.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
package exec
66

7-
import "errors"
7+
import (
8+
"errors"
9+
10+
"github.com/go-interpreter/wagon/wasm"
11+
)
812

913
var (
1014
// ErrSignatureMismatch is the error value used while trapping the VM when
@@ -31,7 +35,11 @@ func (vm *VM) callIndirect() {
3135
if int(tableIndex) >= len(vm.module.TableIndexSpace[0]) {
3236
panic(ErrUndefinedElementIndex)
3337
}
34-
elemIndex := vm.module.TableIndexSpace[0][tableIndex]
38+
tableEntry := vm.module.TableIndexSpace[0][tableIndex]
39+
if !tableEntry.Initialized {
40+
panic(wasm.UninitializedTableEntryError(tableIndex))
41+
}
42+
elemIndex := tableEntry.Index
3543
fnActual := vm.module.FunctionIndexSpace[elemIndex]
3644

3745
if len(fnExpect.ParamTypes) != len(fnActual.Sig.ParamTypes) {

exec/memory.go

+13-4
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ func (vm *VM) fetchBaseAddr() int {
1919

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

2727
// curMem returns a slice to the memory segment pointed to by
@@ -208,7 +208,16 @@ func (vm *VM) currentMemory() {
208208
func (vm *VM) growMemory() {
209209
_ = vm.fetchInt8() // reserved (https://github.com/WebAssembly/design/blob/27ac254c854994103c24834a994be16f74f54186/BinaryEncoding.md#memory-related-operators-described-here)
210210
curLen := len(vm.memory) / wasmPageSize
211-
n := vm.popInt32()
211+
n := vm.popUint32()
212+
213+
maxMem := vm.module.Memory.Entries[0].Limits.Maximum
214+
newPage := uint64(n + uint32(len(vm.memory)/wasmPageSize))
215+
216+
if newPage > 1<<16 || newPage > uint64(maxMem) {
217+
vm.pushInt32(-1)
218+
return
219+
}
220+
212221
vm.memory = append(vm.memory, make([]byte, n*wasmPageSize)...)
213222
vm.pushInt32(int32(curLen))
214223
}

exec/num.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package exec
66

77
import (
8+
"errors"
89
"math"
910
"math/bits"
1011
)
@@ -34,6 +35,9 @@ func (vm *VM) i32Mul() {
3435
func (vm *VM) i32DivS() {
3536
v2 := vm.popInt32()
3637
v1 := vm.popInt32()
38+
if v1 == math.MinInt32 && v2 == -1 {
39+
panic(errors.New("integer overflow"))
40+
}
3741
vm.pushInt32(v1 / v2)
3842
}
3943

@@ -76,19 +80,19 @@ func (vm *VM) i32Xor() {
7680
func (vm *VM) i32Shl() {
7781
v2 := vm.popUint32()
7882
v1 := vm.popUint32()
79-
vm.pushUint32(v1 << v2)
83+
vm.pushUint32(v1 << (v2 % 32))
8084
}
8185

8286
func (vm *VM) i32ShrU() {
8387
v2 := vm.popUint32()
8488
v1 := vm.popUint32()
85-
vm.pushUint32(v1 >> v2)
89+
vm.pushUint32(v1 >> (v2 % 32))
8690
}
8791

8892
func (vm *VM) i32ShrS() {
8993
v2 := vm.popUint32()
9094
v1 := vm.popInt32()
91-
vm.pushInt32(v1 >> v2)
95+
vm.pushInt32(v1 >> (v2 % 32))
9296
}
9397

9498
func (vm *VM) i32Rotl() {
@@ -194,6 +198,9 @@ func (vm *VM) i64Mul() {
194198
func (vm *VM) i64DivS() {
195199
v2 := vm.popInt64()
196200
v1 := vm.popInt64()
201+
if v1 == math.MinInt64 && v2 == -1 {
202+
panic(errors.New("integer overflow"))
203+
}
197204
vm.pushInt64(v1 / v2)
198205
}
199206

@@ -230,19 +237,19 @@ func (vm *VM) i64Xor() {
230237
func (vm *VM) i64Shl() {
231238
v2 := vm.popUint64()
232239
v1 := vm.popUint64()
233-
vm.pushUint64(v1 << v2)
240+
vm.pushUint64(v1 << (v2 % 64))
234241
}
235242

236243
func (vm *VM) i64ShrS() {
237244
v2 := vm.popUint64()
238245
v1 := vm.popInt64()
239-
vm.pushInt64(v1 >> v2)
246+
vm.pushInt64(v1 >> (v2 % 64))
240247
}
241248

242249
func (vm *VM) i64ShrU() {
243250
v2 := vm.popUint64()
244251
v1 := vm.popUint64()
245-
vm.pushUint64(v1 >> v2)
252+
vm.pushUint64(v1 >> (v2 % 64))
246253
}
247254

248255
func (vm *VM) i64Rotl() {

exec/vm.go

+20
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,26 @@ func (vm *VM) Memory() []byte {
207207
return vm.memory
208208
}
209209

210+
// GetExportEntry returns ExportEntry of this VM's Wasm module.
211+
func (vm *VM) GetExportEntry(name string) (wasm.ExportEntry, bool) {
212+
entry, ok := vm.module.Export.Entries[name]
213+
return entry, ok
214+
}
215+
216+
// GetGlobal returns the global value represented as uint64 defined in this VM's Wasm module.
217+
func (vm *VM) GetGlobal(name string) (uint64, bool) {
218+
entry, ok := vm.GetExportEntry(name)
219+
if !ok {
220+
return 0, false
221+
}
222+
index := entry.Index
223+
if int64(index) >= int64(len(vm.globals)) {
224+
return 0, false
225+
}
226+
227+
return vm.globals[index], true
228+
}
229+
210230
func (vm *VM) pushBool(v bool) {
211231
if v {
212232
vm.pushUint64(1)

go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ require (
77
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc
88
golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e // indirect
99
)
10+
11+
// users in some countries cannot access golang.org.
12+
replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190306220234-b354f8bf4d9e

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
22
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
3+
github.com/golang/sys v0.0.0-20190306220234-b354f8bf4d9e h1:Yv9Nf3qPhnbsludlsbTa1z6lOpYbJxHKoh5lXyqfP3I=
4+
github.com/golang/sys v0.0.0-20190306220234-b354f8bf4d9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
35
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc h1:RTUQlKzoZZVG3umWNzOYeFecQLIh+dbxXvJp1zPQJTI=
46
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc/go.mod h1:NoCfSFWosfqMqmmD7hApkirIK9ozpHjxRnRxs1l413A=
5-
golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e h1:UndnRDGP/JcdZX1LBubo1fJ3Jt6GnKREteLJvysiiPE=
6-
golang.org/x/sys v0.0.0-20190306220234-b354f8bf4d9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

tests/run_testcase.sh

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
3+
set -ex
4+
rm -rf temp
5+
mkdir temp
6+
cd temp
7+
8+
if ! which wast2json ; then
9+
wget https://github.com/WebAssembly/wabt/releases/download/1.0.13/wabt-1.0.13-linux.tar.gz
10+
tar -xzvf wabt-1.0.13-linux.tar.gz
11+
WAST2JSON=wabt-1.0.13/wast2json
12+
else
13+
WAST2JSON=wast2json
14+
fi
15+
16+
17+
go build $TAGS -o spec_test ../spec_test_runner.go
18+
19+
for file in ../spectestcase/*.wast ; do
20+
${WAST2JSON} ${file}
21+
done
22+
23+
for json in *.json ; do
24+
./spec_test ${json}
25+
done

0 commit comments

Comments
 (0)