From 9331fe28e89dd22820ee8999d11aa2938c5198cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Bylica?= <chfast@gmail.com>
Date: Fri, 3 Dec 2021 11:04:54 +0100
Subject: [PATCH] core/vm: fill gaps in jump table with opUndefined (#24031)

---
 core/vm/instructions.go |  4 ++++
 core/vm/interpreter.go  |  3 ---
 core/vm/jump_table.go   | 11 ++++++++++-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index cc225e484f48..1e91ff255c6f 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -801,6 +801,10 @@ func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
 	return ret, ErrExecutionReverted
 }
 
+func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+	return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.Code[*pc])}
+}
+
 func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
 	return nil, errStopToken
 }
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 99257d57a831..a4c54b1fb84b 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -193,9 +193,6 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
 		// enough stack items available to perform the operation.
 		op = contract.GetOp(pc)
 		operation := in.cfg.JumpTable[op]
-		if operation == nil {
-			return nil, &ErrInvalidOpCode{opcode: op}
-		}
 		// Validate stack
 		if sLen := stack.len(); sLen < operation.minStack {
 			return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack}
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 676cfc06093e..bb559b594999 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -200,7 +200,7 @@ func newHomesteadInstructionSet() JumpTable {
 // newFrontierInstructionSet returns the frontier instructions
 // that can be executed during the frontier phase.
 func newFrontierInstructionSet() JumpTable {
-	return JumpTable{
+	tbl := JumpTable{
 		STOP: {
 			execute:     opStop,
 			constantGas: 0,
@@ -1002,4 +1002,13 @@ func newFrontierInstructionSet() JumpTable {
 			maxStack:   maxStack(1, 0),
 		},
 	}
+
+	// Fill all unassigned slots with opUndefined.
+	for i, entry := range tbl {
+		if entry == nil {
+			tbl[i] = &operation{execute: opUndefined, maxStack: maxStack(0, 0)}
+		}
+	}
+
+	return tbl
 }