Repository: tetratelabs/wazero
Pull request #2112 (2024-03-04 02:58:52)

validation: return error on unknown opcode after misc prefix
found in https://github.com/tetratelabs/wazero/actions/runs/8135070073/job/22228998097


Patch:
diff --git a/internal/engine/wazevo/backend/isa/amd64/instr.go b/internal/engine/wazevo/backend/isa/amd64/instr.go
index bed379ea..600ae2b1 100644
--- a/internal/engine/wazevo/backend/isa/amd64/instr.go
+++ b/internal/engine/wazevo/backend/isa/amd64/instr.go
@@ -258,6 +258,8 @@ func (i *instruction) String() string {
 		return fmt.Sprintf("xmmcmov%s %s, %s", cond(i.u1), i.op1.format(true), i.op2.format(true))
 	case blendvpd:
 		return fmt.Sprintf("blendvpd %s, %s, %%xmm0", i.op1.format(false), i.op2.format(false))
+	case mfence:
+		return "mfence"
 	default:
 		panic(fmt.Sprintf("BUG: %d", int(i.kind)))
 	}
@@ -754,9 +756,17 @@ const (
 	// blendvpd is https://www.felixcloutier.com/x86/blendvpd.
 	blendvpd
 
+	// mfence is https://www.felixcloutier.com/x86/mfence
+	mfence
+
 	instrMax
 )
 
+func (i *instruction) asMFence() *instruction {
+	i.kind = mfence
+	return i
+}
+
 func (i *instruction) asIdivRemSequence(execCtx, divisor, tmpGp regalloc.VReg, isDiv, signed, _64 bool) *instruction {
 	i.kind = idivRemSequence
 	i.op1 = newOperandReg(execCtx)
@@ -978,6 +988,8 @@ func (k instructionKind) String() string {
 		return "xmmCMov"
 	case idivRemSequence:
 		return "idivRemSequence"
+	case mfence:
+		return "mfence"
 	default:
 		panic("BUG")
 	}
@@ -2218,6 +2230,7 @@ var defKinds = [instrMax]defKind{
 	xmmCMov:                defKindOp2,
 	idivRemSequence:        defKindDivRem,
 	blendvpd:               defKindNone,
+	mfence:                 defKindNone,
 }
 
 // String implements fmt.Stringer.
@@ -2293,6 +2306,7 @@ var useKinds = [instrMax]useKind{
 	xmmCMov:                useKindOp1,
 	idivRemSequence:        useKindDivRem,
 	blendvpd:               useKindBlendvpd,
+	mfence:                 useKindNone,
 }
 
 func (u useKind) String() string {
diff --git a/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go b/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go
index 95de5e8e..2f99e8b5 100644
--- a/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go
+++ b/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go
@@ -1259,6 +1259,12 @@ func (i *instruction) encode(c backend.Compiler) (needsLabelResolution bool) {
 		}
 		i.encode(c)
 
+	case mfence:
+		// https://www.felixcloutier.com/x86/mfence
+		c.EmitByte(0x0f)
+		c.EmitByte(0xae)
+		c.EmitByte(0xf0)
+
 	default:
 		panic(fmt.Sprintf("TODO: %v", i.kind))
 	}
diff --git a/internal/engine/wazevo/backend/isa/amd64/machine.go b/internal/engine/wazevo/backend/isa/amd64/machine.go
index a22f29e2..29575ee0 100644
--- a/internal/engine/wazevo/backend/isa/amd64/machine.go
+++ b/internal/engine/wazevo/backend/isa/amd64/machine.go
@@ -956,6 +956,9 @@ func (m *machine) LowerInstr(instr *ssa.Instruction) {
 		}
 		m.insert(load)
 
+	case ssa.OpcodeFence:
+		m.insert(m.allocateInstr().asMFence())
+
 	default:
 		panic("TODO: lowering " + op.String())
 	}
diff --git a/internal/wasm/func_validation.go b/internal/wasm/func_validation.go
index 592ac869..673d5763 100644
--- a/internal/wasm/func_validation.go
+++ b/internal/wasm/func_validation.go
@@ -1090,6 +1090,8 @@ func (m *Module) validateFunctionWithMaxStackValues(
 				for _, r := range results {
 					valueTypeStack.push(r)
 				}
+			} else {
+				return fmt.Errorf("unknown misc opcode %#x", miscOpcode)
 			}
 		} else if op == OpcodeVecPrefix {
 			pc++
@@ -1393,7 +1395,7 @@ func (m *Module) validateFunctionWithMaxStackValues(
 				}
 				valueTypeStack.push(ValueTypeV128)
 			default:
-				return fmt.Errorf("TODO: SIMD instruction %s will be implemented in #506", vectorInstructionName[vecOpcode])
+				return fmt.Errorf("unknown SIMD instruction %s", vectorInstructionName[vecOpcode])
 			}
 		} else if op == OpcodeBlock {
 			br.Reset(body[pc+1:])


Test patch:
diff --git a/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go b/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go
index b3f9ccf7..be85fa7e 100644
--- a/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go
+++ b/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go
@@ -4046,6 +4046,11 @@ func TestInstruction_format_encode(t *testing.T) {
 			want:       "66440f3815f9",
 			wantFormat: "blendvpd %xmm1, %xmm15, %xmm0",
 		},
+		{
+			setup:      func(i *instruction) { i.asMFence() },
+			want:       "0faef0",
+			wantFormat: "mfence",
+		},
 	} {
 		tc := tc
 		t.Run(tc.wantFormat, func(t *testing.T) {
diff --git a/internal/engine/wazevo/e2e_test.go b/internal/engine/wazevo/e2e_test.go
index ff2ec773..9807ebbe 100644
--- a/internal/engine/wazevo/e2e_test.go
+++ b/internal/engine/wazevo/e2e_test.go
@@ -842,10 +842,9 @@ func TestE2E(t *testing.T) {
 			},
 		},
 		{
-			name:      "atomic_fence",
-			m:         testcases.AtomicFence.Module,
-			features:  api.CoreFeaturesV2 | experimental.CoreFeaturesThreads,
-			skipAMD64: true,
+			name:     "atomic_fence",
+			m:        testcases.AtomicFence.Module,
+			features: api.CoreFeaturesV2 | experimental.CoreFeaturesThreads,
 			calls: []callCase{
 				{params: []uint64{}, expResults: []uint64{}},
 			},
diff --git a/internal/integration_test/fuzzcases/fuzzcases_test.go b/internal/integration_test/fuzzcases/fuzzcases_test.go
index 3d9cc928..feaa3816 100644
--- a/internal/integration_test/fuzzcases/fuzzcases_test.go
+++ b/internal/integration_test/fuzzcases/fuzzcases_test.go
@@ -1043,3 +1043,16 @@ func Test2097(t *testing.T) {
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "unexpected end of function")
 }
+
+func Test2112(t *testing.T) {
+	bin, err := hex.DecodeString("0061736d0100000001050160017e00020100030201000404017000000a06010400fc300b")
+	require.NoError(t, err)
+	if !platform.CompilerSupported() {
+		return
+	}
+
+	r := wazero.NewRuntimeWithConfig(context.Background(), opt.NewRuntimeConfigOptimizingCompiler())
+	_, err = r.Instantiate(ctx, bin)
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "invalid function[0]: unknown misc opcode 0x30")
+}