diff --git a/vm/vm.go b/vm/vm.go index c4c92d571..aa4c3d62e 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -63,7 +63,7 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, ga output, err = vm.call(caller, callee, code, input, value, gas) vm.callDepth -= 1 if err != nil { - err = transfer(callee, caller, value) + err := transfer(callee, caller, value) if err != nil { panic("Could not return value to caller") } @@ -270,7 +270,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga return nil, firstErr(err, ErrInsufficientGas) } offset, size := stack.Pop64(), stack.Pop64() - data, ok := subslice(memory, offset, size) + data, ok := subslice(memory, offset, size, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -309,7 +309,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case CALLDATALOAD: // 0x35 offset := stack.Pop64() - data, ok := subslice(input, offset, 32) + data, ok := subslice(input, offset, 32, true) if !ok { return nil, firstErr(err, ErrInputOutOfBounds) } @@ -324,11 +324,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga memOff := stack.Pop64() inputOff := stack.Pop64() length := stack.Pop64() - data, ok := subslice(input, inputOff, length) + data, ok := subslice(input, inputOff, length, false) if !ok { return nil, firstErr(err, ErrInputOutOfBounds) } - dest, ok := subslice(memory, memOff, length) + dest, ok := subslice(memory, memOff, length, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -344,11 +344,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga memOff := stack.Pop64() codeOff := stack.Pop64() length := stack.Pop64() - data, ok := subslice(code, codeOff, length) + fmt.Println("CODECOPY: codeOff, length, codelength", codeOff, length, len(code)) + data, ok := subslice(code, codeOff, length, false) if !ok { return nil, firstErr(err, ErrCodeOutOfBounds) } - dest, ok := subslice(memory, memOff, length) + dest, ok := subslice(memory, memOff, length, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -386,11 +387,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga memOff := stack.Pop64() codeOff := stack.Pop64() length := stack.Pop64() - data, ok := subslice(code, codeOff, length) + data, ok := subslice(code, codeOff, length, false) if !ok { return nil, firstErr(err, ErrCodeOutOfBounds) } - dest, ok := subslice(memory, memOff, length) + dest, ok := subslice(memory, memOff, length, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -425,7 +426,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case MLOAD: // 0x51 offset := stack.Pop64() - data, ok := subslice(memory, offset, 32) + data, ok := subslice(memory, offset, 32, true) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -434,7 +435,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case MSTORE: // 0x52 offset, data := stack.Pop64(), stack.Pop() - dest, ok := subslice(memory, offset, 32) + dest, ok := subslice(memory, offset, 32, true) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -469,13 +470,13 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga fmt.Printf(" {0x%X : 0x%X}\n", loc, data) case JUMP: // 0x56 - err = jump(code, stack.Pop64()) + err = jump(code, stack.Pop64(), &pc) continue case JUMPI: // 0x57 pos, cond := stack.Pop64(), stack.Pop64() if cond >= 1 { - err = jump(code, pos) + err = jump(code, pos, &pc) continue } fmt.Printf(" ~> false\n") @@ -491,11 +492,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga fmt.Printf(" => %X\n", *gas) case JUMPDEST: // 0x5B + fmt.Printf("\n") // Do nothing case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32: a := uint64(op - PUSH1 + 1) - codeSegment, ok := subslice(code, pc+1, a) + codeSegment, ok := subslice(code, pc+1, a, true) if !ok { return nil, firstErr(err, ErrCodeOutOfBounds) } @@ -521,7 +523,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga for i := 0; i < n; i++ { topics[i] = stack.Pop() } - data, ok := subslice(memory, offset, size) + data, ok := subslice(memory, offset, size, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -537,7 +539,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case CREATE: // 0xF0 contractValue := stack.Pop64() offset, size := stack.Pop64(), stack.Pop64() - input, ok := subslice(memory, offset, size) + input, ok := subslice(memory, offset, size, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -572,7 +574,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga fmt.Printf(" => %X\n", addr) // Get the arguments from the memory - args, ok := subslice(memory, inOffset, inSize) + args, ok := subslice(memory, inOffset, inSize, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -612,7 +614,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga stack.Push(Zero) } else { stack.Push(One) - dest, ok := subslice(memory, retOffset, retSize) + dest, ok := subslice(memory, retOffset, retSize, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -626,7 +628,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case RETURN: // 0xF3 offset, size := stack.Pop64(), stack.Pop64() - ret, ok := subslice(memory, offset, size) + ret, ok := subslice(memory, offset, size, false) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -660,15 +662,19 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga } } -func subslice(data []byte, offset, length uint64) ([]byte, bool) { +func subslice(data []byte, offset, length uint64, flip_ bool) (ret []byte, ok bool) { size := uint64(len(data)) if size < offset { return nil, false } else if size < offset+length { - return data[offset:], false + ret, ok = data[offset:], false } else { - return data[offset : offset+length], true + ret, ok = data[offset:offset+length], true } + if flip_ { + ret = flip(ret) + } + return } func codeGetOp(code []byte, n uint64) OpCode { @@ -679,12 +685,14 @@ func codeGetOp(code []byte, n uint64) OpCode { } } -func jump(code []byte, to uint64) (err error) { +func jump(code []byte, to uint64, pc *uint64) (err error) { dest := codeGetOp(code, to) if dest != JUMPDEST { + fmt.Printf(" ~> %v invalid jump dest %v\n", to, dest) return ErrInvalidJumpDest } fmt.Printf(" ~> %v\n", to) + *pc = to return nil } @@ -714,3 +722,12 @@ func transfer(from, to *Account, amount uint64) error { return nil } } + +func flip(in []byte) []byte { + flipped := make([]byte, len(in)) + for i := 0; i < len(flipped)/2; i++ { + flipped[i] = in[len(in)-1-i] + flipped[len(in)-1-i] = in[i] + } + return flipped +}