Commit 47c96e19 authored by OptimismBot's avatar OptimismBot Committed by GitHub

Merge pull request #6375 from ethereum-optimism/inphi/cannon-undef

cannon: Invalid STF for branch/jump in delay slots
parents 94a01d5b 356acfac
...@@ -174,30 +174,43 @@ func TestEVMFault(t *testing.T) { ...@@ -174,30 +174,43 @@ func TestEVMFault(t *testing.T) {
env, evmState := NewEVMEnv(contracts, addrs) env, evmState := NewEVMEnv(contracts, addrs)
env.Config.Tracer = tracer env.Config.Tracer = tracer
programMem := []byte{0xff, 0xff, 0xff, 0xff} type testInput struct {
state := &State{PC: 0, NextPC: 4, Memory: NewMemory()} name string
initialState := &State{PC: 0, NextPC: 4, Memory: state.Memory} nextPC uint32
err := state.Memory.SetMemoryRange(0, bytes.NewReader(programMem)) insn uint32
require.NoError(t, err, "load program into state")
// set the return address ($ra) to jump into when test completes
state.Registers[31] = endAddr
goState := NewInstrumentedState(state, nil, os.Stdout, os.Stderr)
require.Panics(t, func() { _, _ = goState.Step(true) }, "must panic on illegal instruction")
insnProof := initialState.Memory.MerkleProof(0)
stepWitness := &StepWitness{
State: initialState.EncodeWitness(),
MemProof: insnProof[:],
} }
input := stepWitness.EncodeStepInput() cases := []testInput{
startingGas := uint64(30_000_000) {"illegal instruction", 0, 0xFF_FF_FF_FF},
{"branch in delay-slot", 8, 0x11_02_00_03},
{"jump in delay-slot", 8, 0x0c_00_00_0c},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
state := &State{PC: 0, NextPC: tt.nextPC, Memory: NewMemory()}
initialState := &State{PC: 0, NextPC: tt.nextPC, Memory: state.Memory}
state.Memory.SetMemory(0, tt.insn)
// set the return address ($ra) to jump into when test completes
state.Registers[31] = endAddr
us := NewInstrumentedState(state, nil, os.Stdout, os.Stderr)
require.Panics(t, func() { _, _ = us.Step(true) })
insnProof := initialState.Memory.MerkleProof(0)
stepWitness := &StepWitness{
State: initialState.EncodeWitness(),
MemProof: insnProof[:],
}
input := stepWitness.EncodeStepInput()
startingGas := uint64(30_000_000)
_, _, err = env.Call(vm.AccountRef(sender), addrs.MIPS, input, startingGas, big.NewInt(0)) _, _, err := env.Call(vm.AccountRef(sender), addrs.MIPS, input, startingGas, big.NewInt(0))
require.EqualValues(t, err, vm.ErrExecutionReverted) require.EqualValues(t, err, vm.ErrExecutionReverted)
logs := evmState.Logs() logs := evmState.Logs()
require.Equal(t, 0, len(logs)) require.Equal(t, 0, len(logs))
})
}
} }
func TestHelloEVM(t *testing.T) { func TestHelloEVM(t *testing.T) {
......
...@@ -180,6 +180,10 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -180,6 +180,10 @@ func (m *InstrumentedState) handleSyscall() error {
} }
func (m *InstrumentedState) handleBranch(opcode uint32, insn uint32, rtReg uint32, rs uint32) error { func (m *InstrumentedState) handleBranch(opcode uint32, insn uint32, rtReg uint32, rs uint32) error {
if m.state.NextPC != m.state.PC+4 {
panic("branch in delay slot")
}
shouldBranch := false shouldBranch := false
if opcode == 4 || opcode == 5 { // beq/bne if opcode == 4 || opcode == 5 { // beq/bne
rt := m.state.Registers[rtReg] rt := m.state.Registers[rtReg]
...@@ -246,6 +250,9 @@ func (m *InstrumentedState) handleHiLo(fun uint32, rs uint32, rt uint32, storeRe ...@@ -246,6 +250,9 @@ func (m *InstrumentedState) handleHiLo(fun uint32, rs uint32, rt uint32, storeRe
} }
func (m *InstrumentedState) handleJump(linkReg uint32, dest uint32) error { func (m *InstrumentedState) handleJump(linkReg uint32, dest uint32) error {
if m.state.NextPC != m.state.PC+4 {
panic("jump in delay slot")
}
prevPC := m.state.PC prevPC := m.state.PC
m.state.PC = m.state.NextPC m.state.PC = m.state.NextPC
m.state.NextPC = dest m.state.NextPC = dest
......
This diff is collapsed.
This diff is collapsed.
...@@ -290,6 +290,10 @@ contract MIPS { ...@@ -290,6 +290,10 @@ contract MIPS {
bool shouldBranch = false; bool shouldBranch = false;
if (state.nextPC != state.pc+4) {
revert("branch in delay slot");
}
// beq/bne: Branch on equal / not equal // beq/bne: Branch on equal / not equal
if (_opcode == 4 || _opcode == 5) { if (_opcode == 4 || _opcode == 5) {
uint32 rt = state.registers[_rtReg]; uint32 rt = state.registers[_rtReg];
...@@ -419,6 +423,10 @@ contract MIPS { ...@@ -419,6 +423,10 @@ contract MIPS {
state := 0x80 state := 0x80
} }
if (state.nextPC != state.pc+4) {
revert("jump in delay slot");
}
// Update the next PC to the jump destination. // Update the next PC to the jump destination.
uint32 prevPC = state.pc; uint32 prevPC = state.pc;
state.pc = state.nextPC; state.pc = state.nextPC;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment