Browse Source

vm: fix endianess by flipping on subslic

pull/37/head
Ethan Buchman 10 years ago
parent
commit
acf25835aa
1 changed files with 40 additions and 23 deletions
  1. +40
    -23
      vm/vm.go

+ 40
- 23
vm/vm.go View File

@ -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) output, err = vm.call(caller, callee, code, input, value, gas)
vm.callDepth -= 1 vm.callDepth -= 1
if err != nil { if err != nil {
err = transfer(callee, caller, value)
err := transfer(callee, caller, value)
if err != nil { if err != nil {
panic("Could not return value to caller") 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) return nil, firstErr(err, ErrInsufficientGas)
} }
offset, size := stack.Pop64(), stack.Pop64() offset, size := stack.Pop64(), stack.Pop64()
data, ok := subslice(memory, offset, size)
data, ok := subslice(memory, offset, size, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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 case CALLDATALOAD: // 0x35
offset := stack.Pop64() offset := stack.Pop64()
data, ok := subslice(input, offset, 32)
data, ok := subslice(input, offset, 32, true)
if !ok { if !ok {
return nil, firstErr(err, ErrInputOutOfBounds) 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() memOff := stack.Pop64()
inputOff := stack.Pop64() inputOff := stack.Pop64()
length := stack.Pop64() length := stack.Pop64()
data, ok := subslice(input, inputOff, length)
data, ok := subslice(input, inputOff, length, false)
if !ok { if !ok {
return nil, firstErr(err, ErrInputOutOfBounds) return nil, firstErr(err, ErrInputOutOfBounds)
} }
dest, ok := subslice(memory, memOff, length)
dest, ok := subslice(memory, memOff, length, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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() memOff := stack.Pop64()
codeOff := stack.Pop64() codeOff := stack.Pop64()
length := 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 { if !ok {
return nil, firstErr(err, ErrCodeOutOfBounds) return nil, firstErr(err, ErrCodeOutOfBounds)
} }
dest, ok := subslice(memory, memOff, length)
dest, ok := subslice(memory, memOff, length, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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() memOff := stack.Pop64()
codeOff := stack.Pop64() codeOff := stack.Pop64()
length := stack.Pop64() length := stack.Pop64()
data, ok := subslice(code, codeOff, length)
data, ok := subslice(code, codeOff, length, false)
if !ok { if !ok {
return nil, firstErr(err, ErrCodeOutOfBounds) return nil, firstErr(err, ErrCodeOutOfBounds)
} }
dest, ok := subslice(memory, memOff, length)
dest, ok := subslice(memory, memOff, length, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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 case MLOAD: // 0x51
offset := stack.Pop64() offset := stack.Pop64()
data, ok := subslice(memory, offset, 32)
data, ok := subslice(memory, offset, 32, true)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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 case MSTORE: // 0x52
offset, data := stack.Pop64(), stack.Pop() offset, data := stack.Pop64(), stack.Pop()
dest, ok := subslice(memory, offset, 32)
dest, ok := subslice(memory, offset, 32, true)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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) fmt.Printf(" {0x%X : 0x%X}\n", loc, data)
case JUMP: // 0x56 case JUMP: // 0x56
err = jump(code, stack.Pop64())
err = jump(code, stack.Pop64(), &pc)
continue continue
case JUMPI: // 0x57 case JUMPI: // 0x57
pos, cond := stack.Pop64(), stack.Pop64() pos, cond := stack.Pop64(), stack.Pop64()
if cond >= 1 { if cond >= 1 {
err = jump(code, pos)
err = jump(code, pos, &pc)
continue continue
} }
fmt.Printf(" ~> false\n") 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) fmt.Printf(" => %X\n", *gas)
case JUMPDEST: // 0x5B case JUMPDEST: // 0x5B
fmt.Printf("\n")
// Do nothing // 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: 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) a := uint64(op - PUSH1 + 1)
codeSegment, ok := subslice(code, pc+1, a)
codeSegment, ok := subslice(code, pc+1, a, true)
if !ok { if !ok {
return nil, firstErr(err, ErrCodeOutOfBounds) 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++ { for i := 0; i < n; i++ {
topics[i] = stack.Pop() topics[i] = stack.Pop()
} }
data, ok := subslice(memory, offset, size)
data, ok := subslice(memory, offset, size, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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 case CREATE: // 0xF0
contractValue := stack.Pop64() contractValue := stack.Pop64()
offset, size := stack.Pop64(), stack.Pop64() offset, size := stack.Pop64(), stack.Pop64()
input, ok := subslice(memory, offset, size)
input, ok := subslice(memory, offset, size, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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) fmt.Printf(" => %X\n", addr)
// Get the arguments from the memory // Get the arguments from the memory
args, ok := subslice(memory, inOffset, inSize)
args, ok := subslice(memory, inOffset, inSize, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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) stack.Push(Zero)
} else { } else {
stack.Push(One) stack.Push(One)
dest, ok := subslice(memory, retOffset, retSize)
dest, ok := subslice(memory, retOffset, retSize, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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 case RETURN: // 0xF3
offset, size := stack.Pop64(), stack.Pop64() offset, size := stack.Pop64(), stack.Pop64()
ret, ok := subslice(memory, offset, size)
ret, ok := subslice(memory, offset, size, false)
if !ok { if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds) 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)) size := uint64(len(data))
if size < offset { if size < offset {
return nil, false return nil, false
} else if size < offset+length { } else if size < offset+length {
return data[offset:], false
ret, ok = data[offset:], false
} else { } 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 { 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) dest := codeGetOp(code, to)
if dest != JUMPDEST { if dest != JUMPDEST {
fmt.Printf(" ~> %v invalid jump dest %v\n", to, dest)
return ErrInvalidJumpDest return ErrInvalidJumpDest
} }
fmt.Printf(" ~> %v\n", to) fmt.Printf(" ~> %v\n", to)
*pc = to
return nil return nil
} }
@ -714,3 +722,12 @@ func transfer(from, to *Account, amount uint64) error {
return nil 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
}

Loading…
Cancel
Save