vm: check instruction offset is valid before subsequent IP move

Reference implementation:
e167f03e25/src/neo-vm/ExecutionContext.cs (L77).

Turns out that exception-related code (try\finally handling) is the only
place where next instruction pointer bounds are not pre-checked before
assignment. This statement is true for both go and C# implementations.
However, C# code has duplicate check located inside the
InstructionPointer setter for all instructions except the
exception-related ones. Neo-go code doesn't perform this duplicate check.
Thus, C# VM FAULTs execution in case of invalid TRY/FINALLY offsets, and
neo-go VM does not.

This commit reverts a part of
https://github.com/nspcc-dev/neo-go/pull/2396. This bug is discovered
thanks to test added in https://github.com/neo-project/neo-vm/pull/453.
This commit is contained in:
Anna Shaleva 2022-05-11 13:47:26 +03:00
parent d1588115a2
commit 3be37e8c5b

View file

@ -85,6 +85,9 @@ func (c *Context) NextIP() int {
// Jump unconditionally moves the next instruction pointer to the specified location. // Jump unconditionally moves the next instruction pointer to the specified location.
func (c *Context) Jump(pos int) { func (c *Context) Jump(pos int) {
if pos < 0 || pos > len(c.prog) {
panic("instruction offset is out of range")
}
c.nextip = pos c.nextip = pos
} }
@ -95,9 +98,6 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) {
var err error var err error
c.ip = c.nextip c.ip = c.nextip
if c.ip < 0 {
return 0, nil, errors.New("invalid instruction offset")
}
if c.ip >= len(c.prog) { if c.ip >= len(c.prog) {
return opcode.RET, nil, nil return opcode.RET, nil, nil
} }