From 3be37e8c5b16c22371c4e053ceee3efe5f6e1981 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 11 May 2022 13:47:26 +0300 Subject: [PATCH] vm: check instruction offset is valid before subsequent IP move Reference implementation: https://github.com/neo-project/neo-vm/blob/e167f03e25abd8232316fa96b54fbbc01526f0ab/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. --- pkg/vm/context.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/vm/context.go b/pkg/vm/context.go index c6440c9b6..09c0ceaf5 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -85,6 +85,9 @@ func (c *Context) NextIP() int { // Jump unconditionally moves the next instruction pointer to the specified location. func (c *Context) Jump(pos int) { + if pos < 0 || pos > len(c.prog) { + panic("instruction offset is out of range") + } c.nextip = pos } @@ -95,9 +98,6 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) { var err error c.ip = c.nextip - if c.ip < 0 { - return 0, nil, errors.New("invalid instruction offset") - } if c.ip >= len(c.prog) { return opcode.RET, nil, nil }