diff --git a/rvgo/fast/vm.go b/rvgo/fast/vm.go index 6700e078..98cdc767 100644 --- a/rvgo/fast/vm.go +++ b/rvgo/fast/vm.go @@ -587,6 +587,12 @@ func (inst *InstrumentedState) riscvStep() (outErr error) { switch opcode { case 0x03: // 000_0011: memory loading // LB, LH, LW, LD, LBU, LHU, LWU + + // bits[14:12] set to 111 are reserved + if eq64(funct3, toU64(0x7)) != 0 { + revertWithCode(riscv.ErrInvalidSyscall, fmt.Errorf("illegal instruction %d: reserved instruction encoding", instr)) + } + imm := parseImmTypeI(instr) signed := iszero64(and64(funct3, toU64(4))) // 4 = 100 -> bitflag size := shl64(and64(funct3, toU64(3)), toU64(1)) // 3 = 11 -> 1, 2, 4, 8 bytes size diff --git a/rvgo/slow/vm.go b/rvgo/slow/vm.go index 8dc15b41..c8294b77 100644 --- a/rvgo/slow/vm.go +++ b/rvgo/slow/vm.go @@ -771,6 +771,12 @@ func Step(calldata []byte, po PreimageOracle) (stateHash common.Hash, outErr err switch opcode.val() { case 0x03: // 000_0011: memory loading // LB, LH, LW, LD, LBU, LHU, LWU + + // bits[14:12] set to 111 are reserved + if eq64(funct3, toU64(0x7)) != (U64{}) { + revertWithCode(riscv.ErrInvalidSyscall, fmt.Errorf("illegal instruction %d: reserved instruction encoding", instr)) + } + imm := parseImmTypeI(instr) signed := iszero64(and64(funct3, toU64(4))) // 4 = 100 -> bitflag size := shl64(and64(funct3, toU64(3)), toU64(1)) // 3 = 11 -> 1, 2, 4, 8 bytes size diff --git a/rvsol/src/RISCV.sol b/rvsol/src/RISCV.sol index a8744f62..16a409ec 100644 --- a/rvsol/src/RISCV.sol +++ b/rvsol/src/RISCV.sol @@ -1149,6 +1149,10 @@ contract RISCV is IBigStepper { let pc_ := _pc // 000_0011: memory loading // LB, LH, LW, LD, LBU, LHU, LWU + + // bits[14:12] set to 111 are reserved + if eq64(funct3, toU64(0x7)) { revertWithCode(0xf001ca11) } + let imm := parseImmTypeI(instr) let signed := iszero64(and64(funct3, toU64(4))) // 4 = 100 -> bitflag let size := shl64(and64(funct3, toU64(3)), toU64(1)) // 3 = 11 -> 1, 2, 4, 8 bytes size diff --git a/rvsol/test/RISCV.t.sol b/rvsol/test/RISCV.t.sol index e4b0d1fd..5fc0396c 100644 --- a/rvsol/test/RISCV.t.sol +++ b/rvsol/test/RISCV.t.sol @@ -2460,6 +2460,19 @@ contract RISCV_Test is CommonTest { riscv.step(encodedState, proof, 0); } + function test_reserved_load_instruction() public { + bytes32 value = hex"61fb11d66dcc9d48"; + uint16 offset = 0x6bf; + uint64 addr = 0xd34d + offset; + uint32 insn = encodeIType(0x3, 21, 0x7, 4, offset); // lhu x21, funct 0x7, offset(x4) + (State memory state, bytes memory proof) = constructRISCVState(0, insn, addr, value); + state.registers[4] = 0xd34d; + bytes memory encodedState = encodeState(state); + + vm.expectRevert(hex"00000000000000000000000000000000000000000000000000000000f001ca11"); + riscv.step(encodedState, proof, 0); + } + function test_revert_unaligned_jal_instruction() public { // 0xbef054ae % 4 != 0 uint32 imm = 0xbef054ae;