mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-29 06:01:21 +00:00
vm: fix endianess by flipping on subslic
This commit is contained in:
parent
7bf34b1883
commit
acf25835aa
63
vm/vm.go
63
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)
|
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…
x
Reference in New Issue
Block a user