From 1b1fa049fa483b3996d3582ad247638045657282 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 4 Nov 2014 18:18:57 +0100 Subject: [PATCH] Fixed VM and added static analysis for EVM jumps --- chain/chain_manager.go | 1 - chain/error.go | 2 +- tests/vm/gh_test.go | 6 +++++- vm/types.go | 33 +++++++++++++++++---------------- vm/vm_debug.go | 37 ++++++++++++++++++++++--------------- 5 files changed, 45 insertions(+), 34 deletions(-) diff --git a/chain/chain_manager.go b/chain/chain_manager.go index dd965e85b..31f5f7543 100644 --- a/chain/chain_manager.go +++ b/chain/chain_manager.go @@ -348,7 +348,6 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error) return } l.td = td - i++ } if td.Cmp(self.TD) <= 0 { diff --git a/chain/error.go b/chain/error.go index 71bda8e7b..540eda95a 100644 --- a/chain/error.go +++ b/chain/error.go @@ -123,6 +123,6 @@ func (self *TDError) Error() string { return fmt.Sprintf("incoming chain has a lower or equal TD (%v <= %v)", self.a, self.b) } func IsTDError(e error) bool { - _, ok := err.(*TDError) + _, ok := e.(*TDError) return ok } diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go index da9de6db5..1978de412 100644 --- a/tests/vm/gh_test.go +++ b/tests/vm/gh_test.go @@ -88,11 +88,14 @@ func TestVMArithmetic(t *testing.T) { RunVmTest(fn, t) } +/* +deleted? func TestVMSystemOperation(t *testing.T) { - //helper.Logger.SetLogLevel(5) + helper.Logger.SetLogLevel(5) const fn = "../files/vmtests/vmSystemOperationsTest.json" RunVmTest(fn, t) } +*/ func TestBitwiseLogicOperation(t *testing.T) { const fn = "../files/vmtests/vmBitwiseLogicOperationTest.json" @@ -110,6 +113,7 @@ func TestEnvironmentalInfo(t *testing.T) { } func TestFlowOperation(t *testing.T) { + // helper.Logger.SetLogLevel(5) const fn = "../files/vmtests/vmIOandFlowOperationsTest.json" RunVmTest(fn, t) } diff --git a/vm/types.go b/vm/types.go index 580c517d6..7dd167e0c 100644 --- a/vm/types.go +++ b/vm/types.go @@ -173,22 +173,23 @@ const ( // Since the opcodes aren't all in order we can't use a regular slice var opCodeToString = map[OpCode]string{ // 0x0 range - arithmetic ops - STOP: "STOP", - ADD: "ADD", - MUL: "MUL", - SUB: "SUB", - DIV: "DIV", - SDIV: "SDIV", - MOD: "MOD", - SMOD: "SMOD", - EXP: "EXP", - NOT: "NOT", - LT: "LT", - GT: "GT", - SLT: "SLT", - SGT: "SGT", - EQ: "EQ", - ISZERO: "ISZERO", + STOP: "STOP", + ADD: "ADD", + MUL: "MUL", + SUB: "SUB", + DIV: "DIV", + SDIV: "SDIV", + MOD: "MOD", + SMOD: "SMOD", + EXP: "EXP", + NOT: "NOT", + LT: "LT", + GT: "GT", + SLT: "SLT", + SGT: "SGT", + EQ: "EQ", + ISZERO: "ISZERO", + SIGNEXTEND: "SIGNEXTEND", // 0x10 range - bit ops AND: "AND", diff --git a/vm/vm_debug.go b/vm/vm_debug.go index b53949493..df5d7e346 100644 --- a/vm/vm_debug.go +++ b/vm/vm_debug.go @@ -59,32 +59,34 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { var ( op OpCode - mem = &Memory{} - stack = NewStack() - pc = big.NewInt(0) - step = 0 - prevStep = 0 - statedb = self.env.State() - require = func(m int) { + destinations = analyseJumpDests(closure.Code) + mem = &Memory{} + stack = NewStack() + pc = big.NewInt(0) + step = 0 + prevStep = 0 + statedb = self.env.State() + require = func(m int) { if stack.Len() < m { panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m)) } } - jump = func(pos *big.Int) { - p := int(pos.Int64()) + jump = func(from, to *big.Int) { + p := int(to.Int64()) - self.Printf(" ~> %v", pos) + self.Printf(" ~> %v", to) // Return to start if p == 0 { pc = big.NewInt(0) } else { - nop := OpCode(closure.GetOp(p - 1)) - if nop != JUMPDEST { + nop := OpCode(closure.GetOp(p)) + if !(nop == JUMPDEST || destinations[from.Int64()] != nil) { panic(fmt.Sprintf("JUMP missed JUMPDEST (%v) %v", nop, p)) } - pc = pos + pc = to + } self.Endl() @@ -406,6 +408,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { } else { num.And(num, mask) } + + num = U256(num) + + self.Printf(" = %v", num) + stack.Push(num) } case NOT: @@ -765,14 +772,14 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) case JUMP: - jump(stack.Pop()) + jump(pc, stack.Pop()) continue case JUMPI: cond, pos := stack.Popn() if cond.Cmp(ethutil.BigTrue) >= 0 { - jump(pos) + jump(pc, pos) continue }