1package wasm
2
3import (
4 "bytes"
5 "errors"
6 "fmt"
7 "strconv"
8 "strings"
9
10 "github.com/tetratelabs/wazero/api"
11 "github.com/tetratelabs/wazero/experimental"
12 "github.com/tetratelabs/wazero/internal/leb128"
13)
14
15// The wazero specific limitation described at RATIONALE.md.
16const maximumValuesOnStack = 1 << 27
17
18// validateFunction validates the instruction sequence of a function.
19// following the specification https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#instructions%E2%91%A2.
20//
21// * idx is the index in the FunctionSection
22// * functions are the function index, which is prefixed by imports. The value is the TypeSection index.
23// * globals are the global index, which is prefixed by imports.
24// * memory is the potentially imported memory and can be nil.
25// * table is the potentially imported table and can be nil.
26// * declaredFunctionIndexes is the set of function indexes declared by declarative element segments which can be acceed by OpcodeRefFunc instruction.
27//
28// Returns an error if the instruction sequence is not valid,
29// or potentially it can exceed the maximum number of values on the stack.
30func (m *Module) validateFunction(sts *stacks, enabledFeatures api.CoreFeatures, idx Index, functions []Index,
31 globals []GlobalType, memory *Memory, tables []Table, declaredFunctionIndexes map[Index]struct{}, br *bytes.Reader,
32) error {
33 return m.validateFunctionWithMaxStackValues(sts, enabledFeatures, idx, functions, globals, memory, tables, maximumValuesOnStack, declaredFunctionIndexes, br)
34}
35
36func readMemArg(pc uint64, body []byte) (align, offset uint32, read uint64, err error) {
37 align, num, err := leb128.LoadUint32(body[pc:])
38 if err != nil {
39 err = fmt.Errorf("read memory align: %v", err)
40 return
41 }
42 read += num
43
44 offset, num, err = leb128.LoadUint32(body[pc+num:])
45 if err != nil {
46 err = fmt.Errorf("read memory offset: %v", err)
47 return
48 }
49
50 read += num
51 return align, offset, read, nil
52}
53
54// validateFunctionWithMaxStackValues is like validateFunction, but allows overriding maxStackValues for testing.
55//
56// * stacks is to track the state of Wasm value and control frame stacks at anypoint of execution, and reused to reduce allocation.
57// * maxStackValues is the maximum height of values stack which the target is allowed to reach.
58func (m *Module) validateFunctionWithMaxStackValues(
59 sts *stacks,
60 enabledFeatures api.CoreFeatures,
61 idx Index,
62 functions []Index,
63 globals []GlobalType,
64 memory *Memory,
65 tables []Table,
66 maxStackValues int,
67 declaredFunctionIndexes map[Index]struct{},
68 br *bytes.Reader,
69) error {
70 functionType := &m.TypeSection[m.FunctionSection[idx]]
71 code := &m.CodeSection[idx]
72 body := code.Body
73 localTypes := code.LocalTypes
74
75 sts.reset(functionType)
76 valueTypeStack := &sts.vs
77 // We start with the outermost control block which is for function return if the code branches into it.
78 controlBlockStack := &sts.cs
79
80 // Now start walking through all the instructions in the body while tracking
81 // control blocks and value types to check the validity of all instructions.
82 for pc := uint64(0); pc < uint64(len(body)); pc++ {
83 op := body[pc]
84 if false {
85 var instName string
86 if op == OpcodeMiscPrefix {
87 instName = MiscInstructionName(body[pc+1])
88 } else if op == OpcodeVecPrefix {
89 instName = VectorInstructionName(body[pc+1])
90 } else if op == OpcodeAtomicPrefix {
91 instName = AtomicInstructionName(body[pc+1])
92 } else {
93 instName = InstructionName(op)
94 }
95 fmt.Printf("handling %s, stack=%s, blocks: %v\n", instName, valueTypeStack.stack, controlBlockStack)
96 }
97
98 if len(controlBlockStack.stack) == 0 {
99 return fmt.Errorf("unexpected end of function at pc=%#x", pc)
100 }
101
102 if OpcodeI32Load <= op && op <= OpcodeI64Store32 {
103 if memory == nil {
104 return fmt.Errorf("memory must exist for %s", InstructionName(op))
105 }
106 pc++
107 align, _, read, err := readMemArg(pc, body)
108 if err != nil {
109 return err
110 }
111 pc += read - 1
112 switch op {
113 case OpcodeI32Load:
114 if 1<<align > 32/8 {
115 return fmt.Errorf("invalid memory alignment")
116 }
117 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
118 return err
119 }
120 valueTypeStack.push(ValueTypeI32)
121 case OpcodeF32Load:
122 if 1<<align > 32/8 {
123 return fmt.Errorf("invalid memory alignment")
124 }
125 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
126 return err
127 }
128 valueTypeStack.push(ValueTypeF32)
129 case OpcodeI32Store:
130 if 1<<align > 32/8 {
131 return fmt.Errorf("invalid memory alignment")
132 }
133 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
134 return err
135 }
136 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
137 return err
138 }
139 case OpcodeF32Store:
140 if 1<<align > 32/8 {
141 return fmt.Errorf("invalid memory alignment")
142 }
143 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
144 return err
145 }
146 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
147 return err
148 }
149 case OpcodeI64Load:
150 if 1<<align > 64/8 {
151 return fmt.Errorf("invalid memory alignment")
152 }
153 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
154 return err
155 }
156 valueTypeStack.push(ValueTypeI64)
157 case OpcodeF64Load:
158 if 1<<align > 64/8 {
159 return fmt.Errorf("invalid memory alignment")
160 }
161 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
162 return err
163 }
164 valueTypeStack.push(ValueTypeF64)
165 case OpcodeI64Store:
166 if 1<<align > 64/8 {
167 return fmt.Errorf("invalid memory alignment")
168 }
169 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
170 return err
171 }
172 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
173 return err
174 }
175 case OpcodeF64Store:
176 if 1<<align > 64/8 {
177 return fmt.Errorf("invalid memory alignment")
178 }
179 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
180 return err
181 }
182 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
183 return err
184 }
185 case OpcodeI32Load8S:
186 if 1<<align > 1 {
187 return fmt.Errorf("invalid memory alignment")
188 }
189 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
190 return err
191 }
192 valueTypeStack.push(ValueTypeI32)
193 case OpcodeI32Load8U:
194 if 1<<align > 1 {
195 return fmt.Errorf("invalid memory alignment")
196 }
197 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
198 return err
199 }
200 valueTypeStack.push(ValueTypeI32)
201 case OpcodeI64Load8S, OpcodeI64Load8U:
202 if 1<<align > 1 {
203 return fmt.Errorf("invalid memory alignment")
204 }
205 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
206 return err
207 }
208 valueTypeStack.push(ValueTypeI64)
209 case OpcodeI32Store8:
210 if 1<<align > 1 {
211 return fmt.Errorf("invalid memory alignment")
212 }
213 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
214 return err
215 }
216 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
217 return err
218 }
219 case OpcodeI64Store8:
220 if 1<<align > 1 {
221 return fmt.Errorf("invalid memory alignment")
222 }
223 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
224 return err
225 }
226 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
227 return err
228 }
229 case OpcodeI32Load16S, OpcodeI32Load16U:
230 if 1<<align > 16/8 {
231 return fmt.Errorf("invalid memory alignment")
232 }
233 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
234 return err
235 }
236 valueTypeStack.push(ValueTypeI32)
237 case OpcodeI64Load16S, OpcodeI64Load16U:
238 if 1<<align > 16/8 {
239 return fmt.Errorf("invalid memory alignment")
240 }
241 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
242 return err
243 }
244 valueTypeStack.push(ValueTypeI64)
245 case OpcodeI32Store16:
246 if 1<<align > 16/8 {
247 return fmt.Errorf("invalid memory alignment")
248 }
249 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
250 return err
251 }
252 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
253 return err
254 }
255 case OpcodeI64Store16:
256 if 1<<align > 16/8 {
257 return fmt.Errorf("invalid memory alignment")
258 }
259 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
260 return err
261 }
262 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
263 return err
264 }
265 case OpcodeI64Load32S, OpcodeI64Load32U:
266 if 1<<align > 32/8 {
267 return fmt.Errorf("invalid memory alignment")
268 }
269 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
270 return err
271 }
272 valueTypeStack.push(ValueTypeI64)
273 case OpcodeI64Store32:
274 if 1<<align > 32/8 {
275 return fmt.Errorf("invalid memory alignment")
276 }
277 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
278 return err
279 }
280 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
281 return err
282 }
283 }
284 } else if OpcodeMemorySize <= op && op <= OpcodeMemoryGrow {
285 if memory == nil {
286 return fmt.Errorf("memory must exist for %s", InstructionName(op))
287 }
288 pc++
289 val, num, err := leb128.LoadUint32(body[pc:])
290 if err != nil {
291 return fmt.Errorf("read immediate: %v", err)
292 }
293 if val != 0 || num != 1 {
294 return fmt.Errorf("memory instruction reserved bytes not zero with 1 byte")
295 }
296 switch Opcode(op) {
297 case OpcodeMemoryGrow:
298 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
299 return err
300 }
301 valueTypeStack.push(ValueTypeI32)
302 case OpcodeMemorySize:
303 valueTypeStack.push(ValueTypeI32)
304 }
305 pc += num - 1
306 } else if OpcodeI32Const <= op && op <= OpcodeF64Const {
307 pc++
308 switch Opcode(op) {
309 case OpcodeI32Const:
310 _, num, err := leb128.LoadInt32(body[pc:])
311 if err != nil {
312 return fmt.Errorf("read i32 immediate: %s", err)
313 }
314 pc += num - 1
315 valueTypeStack.push(ValueTypeI32)
316 case OpcodeI64Const:
317 _, num, err := leb128.LoadInt64(body[pc:])
318 if err != nil {
319 return fmt.Errorf("read i64 immediate: %v", err)
320 }
321 valueTypeStack.push(ValueTypeI64)
322 pc += num - 1
323 case OpcodeF32Const:
324 valueTypeStack.push(ValueTypeF32)
325 pc += 3
326 case OpcodeF64Const:
327 valueTypeStack.push(ValueTypeF64)
328 pc += 7
329 }
330 } else if OpcodeLocalGet <= op && op <= OpcodeGlobalSet {
331 pc++
332 index, num, err := leb128.LoadUint32(body[pc:])
333 if err != nil {
334 return fmt.Errorf("read immediate: %v", err)
335 }
336 pc += num - 1
337 switch op {
338 case OpcodeLocalGet:
339 inputLen := uint32(len(functionType.Params))
340 if l := uint32(len(localTypes)) + inputLen; index >= l {
341 return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
342 OpcodeLocalGetName, index, l)
343 }
344 if index < inputLen {
345 valueTypeStack.push(functionType.Params[index])
346 } else {
347 valueTypeStack.push(localTypes[index-inputLen])
348 }
349 case OpcodeLocalSet:
350 inputLen := uint32(len(functionType.Params))
351 if l := uint32(len(localTypes)) + inputLen; index >= l {
352 return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
353 OpcodeLocalSetName, index, l)
354 }
355 var expType ValueType
356 if index < inputLen {
357 expType = functionType.Params[index]
358 } else {
359 expType = localTypes[index-inputLen]
360 }
361 if err := valueTypeStack.popAndVerifyType(expType); err != nil {
362 return err
363 }
364 case OpcodeLocalTee:
365 inputLen := uint32(len(functionType.Params))
366 if l := uint32(len(localTypes)) + inputLen; index >= l {
367 return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
368 OpcodeLocalTeeName, index, l)
369 }
370 var expType ValueType
371 if index < inputLen {
372 expType = functionType.Params[index]
373 } else {
374 expType = localTypes[index-inputLen]
375 }
376 if err := valueTypeStack.popAndVerifyType(expType); err != nil {
377 return err
378 }
379 valueTypeStack.push(expType)
380 case OpcodeGlobalGet:
381 if index >= uint32(len(globals)) {
382 return fmt.Errorf("invalid index for %s", OpcodeGlobalGetName)
383 }
384 valueTypeStack.push(globals[index].ValType)
385 case OpcodeGlobalSet:
386 if index >= uint32(len(globals)) {
387 return fmt.Errorf("invalid global index")
388 } else if !globals[index].Mutable {
389 return fmt.Errorf("%s when not mutable", OpcodeGlobalSetName)
390 } else if err := valueTypeStack.popAndVerifyType(
391 globals[index].ValType); err != nil {
392 return err
393 }
394 }
395 } else if op == OpcodeBr {
396 pc++
397 index, num, err := leb128.LoadUint32(body[pc:])
398 if err != nil {
399 return fmt.Errorf("read immediate: %v", err)
400 } else if int(index) >= len(controlBlockStack.stack) {
401 return fmt.Errorf("invalid %s operation: index out of range", OpcodeBrName)
402 }
403 pc += num - 1
404 // Check type soundness.
405 target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
406 var targetResultType []ValueType
407 if target.op == OpcodeLoop {
408 targetResultType = target.blockType.Params
409 } else {
410 targetResultType = target.blockType.Results
411 }
412 if err = valueTypeStack.popResults(op, targetResultType, false); err != nil {
413 return err
414 }
415 // br instruction is stack-polymorphic.
416 valueTypeStack.unreachable()
417 } else if op == OpcodeBrIf {
418 pc++
419 index, num, err := leb128.LoadUint32(body[pc:])
420 if err != nil {
421 return fmt.Errorf("read immediate: %v", err)
422 } else if int(index) >= len(controlBlockStack.stack) {
423 return fmt.Errorf(
424 "invalid ln param given for %s: index=%d with %d for the current label stack length",
425 OpcodeBrIfName, index, len(controlBlockStack.stack))
426 }
427 pc += num - 1
428 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
429 return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrIfName)
430 }
431 // Check type soundness.
432 target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
433 var targetResultType []ValueType
434 if target.op == OpcodeLoop {
435 targetResultType = target.blockType.Params
436 } else {
437 targetResultType = target.blockType.Results
438 }
439 if err := valueTypeStack.popResults(op, targetResultType, false); err != nil {
440 return err
441 }
442 // Push back the result
443 for _, t := range targetResultType {
444 valueTypeStack.push(t)
445 }
446 } else if op == OpcodeBrTable {
447 pc++
448 br.Reset(body[pc:])
449 nl, num, err := leb128.DecodeUint32(br)
450 if err != nil {
451 return fmt.Errorf("read immediate: %w", err)
452 }
453
454 sts.ls = sts.ls[:0]
455 for i := uint32(0); i < nl; i++ {
456 l, n, err := leb128.DecodeUint32(br)
457 if err != nil {
458 return fmt.Errorf("read immediate: %w", err)
459 }
460 num += n
461 sts.ls = append(sts.ls, l)
462 }
463 ln, n, err := leb128.DecodeUint32(br)
464 if err != nil {
465 return fmt.Errorf("read immediate: %w", err)
466 } else if int(ln) >= len(controlBlockStack.stack) {
467 return fmt.Errorf(
468 "invalid ln param given for %s: ln=%d with %d for the current label stack length",
469 OpcodeBrTableName, ln, len(controlBlockStack.stack))
470 }
471 pc += n + num - 1
472 // Check type soundness.
473 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
474 return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrTableName)
475 }
476 lnLabel := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(ln)]
477 var defaultLabelType []ValueType
478 // Below, we might modify the slice in case of unreachable. Therefore,
479 // we have to copy the content of block result types, otherwise the original
480 // function type might result in invalid value types if the block is the outermost label
481 // which equals the function's type.
482 if lnLabel.op != OpcodeLoop { // Loop operation doesn't require results since the continuation is the beginning of the loop.
483 defaultLabelType = make([]ValueType, len(lnLabel.blockType.Results))
484 copy(defaultLabelType, lnLabel.blockType.Results)
485 } else {
486 defaultLabelType = make([]ValueType, len(lnLabel.blockType.Params))
487 copy(defaultLabelType, lnLabel.blockType.Params)
488 }
489
490 if enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) {
491 // As of reference-types proposal, br_table on unreachable state
492 // can choose unknown types for expected parameter types for each label.
493 // https://github.com/WebAssembly/reference-types/pull/116
494 for i := range defaultLabelType {
495 index := len(defaultLabelType) - 1 - i
496 exp := defaultLabelType[index]
497 actual, err := valueTypeStack.pop()
498 if err != nil {
499 return err
500 }
501 if actual == valueTypeUnknown {
502 // Re-assign the expected type to unknown.
503 defaultLabelType[index] = valueTypeUnknown
504 } else if actual != exp {
505 return typeMismatchError(true, OpcodeBrTableName, actual, exp, i)
506 }
507 }
508 } else {
509 if err = valueTypeStack.popResults(op, defaultLabelType, false); err != nil {
510 return err
511 }
512 }
513
514 for _, l := range sts.ls {
515 if int(l) >= len(controlBlockStack.stack) {
516 return fmt.Errorf("invalid l param given for %s", OpcodeBrTableName)
517 }
518 label := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(l)]
519 var tableLabelType []ValueType
520 if label.op != OpcodeLoop {
521 tableLabelType = label.blockType.Results
522 } else {
523 tableLabelType = label.blockType.Params
524 }
525 if len(defaultLabelType) != len(tableLabelType) {
526 return fmt.Errorf("inconsistent block type length for %s at %d; %v (ln=%d) != %v (l=%d)", OpcodeBrTableName, l, defaultLabelType, ln, tableLabelType, l)
527 }
528 for i := range defaultLabelType {
529 if defaultLabelType[i] != valueTypeUnknown && defaultLabelType[i] != tableLabelType[i] {
530 return fmt.Errorf("incosistent block type for %s at %d", OpcodeBrTableName, l)
531 }
532 }
533 }
534
535 // br_table instruction is stack-polymorphic.
536 valueTypeStack.unreachable()
537 } else if op == OpcodeCall {
538 pc++
539 index, num, err := leb128.LoadUint32(body[pc:])
540 if err != nil {
541 return fmt.Errorf("read immediate: %v", err)
542 }
543 pc += num - 1
544 if int(index) >= len(functions) {
545 return fmt.Errorf("invalid function index")
546 }
547 funcType := &m.TypeSection[functions[index]]
548 for i := 0; i < len(funcType.Params); i++ {
549 if err := valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
550 return fmt.Errorf("type mismatch on %s operation param type: %v", OpcodeCallName, err)
551 }
552 }
553 for _, exp := range funcType.Results {
554 valueTypeStack.push(exp)
555 }
556 } else if op == OpcodeCallIndirect {
557 pc++
558 typeIndex, num, err := leb128.LoadUint32(body[pc:])
559 if err != nil {
560 return fmt.Errorf("read immediate: %v", err)
561 }
562 pc += num
563
564 if int(typeIndex) >= len(m.TypeSection) {
565 return fmt.Errorf("invalid type index at %s: %d", OpcodeCallIndirectName, typeIndex)
566 }
567
568 tableIndex, num, err := leb128.LoadUint32(body[pc:])
569 if err != nil {
570 return fmt.Errorf("read table index: %v", err)
571 }
572 pc += num - 1
573 if tableIndex != 0 {
574 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
575 return fmt.Errorf("table index must be zero but was %d: %w", tableIndex, err)
576 }
577 }
578
579 if tableIndex >= uint32(len(tables)) {
580 return fmt.Errorf("unknown table index: %d", tableIndex)
581 }
582
583 table := tables[tableIndex]
584 if table.Type != RefTypeFuncref {
585 return fmt.Errorf("table is not funcref type but was %s for %s", RefTypeName(table.Type), OpcodeCallIndirectName)
586 }
587
588 if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
589 return fmt.Errorf("cannot pop the offset in table for %s", OpcodeCallIndirectName)
590 }
591 funcType := &m.TypeSection[typeIndex]
592 for i := 0; i < len(funcType.Params); i++ {
593 if err = valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
594 return fmt.Errorf("type mismatch on %s operation input type", OpcodeCallIndirectName)
595 }
596 }
597 for _, exp := range funcType.Results {
598 valueTypeStack.push(exp)
599 }
600 } else if OpcodeI32Eqz <= op && op <= OpcodeI64Extend32S {
601 switch op {
602 case OpcodeI32Eqz:
603 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
604 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32EqzName, err)
605 }
606 valueTypeStack.push(ValueTypeI32)
607 case OpcodeI32Eq, OpcodeI32Ne, OpcodeI32LtS,
608 OpcodeI32LtU, OpcodeI32GtS, OpcodeI32GtU, OpcodeI32LeS,
609 OpcodeI32LeU, OpcodeI32GeS, OpcodeI32GeU:
610 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
611 return fmt.Errorf("cannot pop the 1st i32 operand for %s: %v", InstructionName(op), err)
612 }
613 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
614 return fmt.Errorf("cannot pop the 2nd i32 operand for %s: %v", InstructionName(op), err)
615 }
616 valueTypeStack.push(ValueTypeI32)
617 case OpcodeI64Eqz:
618 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
619 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64EqzName, err)
620 }
621 valueTypeStack.push(ValueTypeI32)
622 case OpcodeI64Eq, OpcodeI64Ne, OpcodeI64LtS,
623 OpcodeI64LtU, OpcodeI64GtS, OpcodeI64GtU,
624 OpcodeI64LeS, OpcodeI64LeU, OpcodeI64GeS, OpcodeI64GeU:
625 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
626 return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
627 }
628 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
629 return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
630 }
631 valueTypeStack.push(ValueTypeI32)
632 case OpcodeF32Eq, OpcodeF32Ne, OpcodeF32Lt, OpcodeF32Gt, OpcodeF32Le, OpcodeF32Ge:
633 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
634 return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
635 }
636 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
637 return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
638 }
639 valueTypeStack.push(ValueTypeI32)
640 case OpcodeF64Eq, OpcodeF64Ne, OpcodeF64Lt, OpcodeF64Gt, OpcodeF64Le, OpcodeF64Ge:
641 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
642 return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
643 }
644 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
645 return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
646 }
647 valueTypeStack.push(ValueTypeI32)
648 case OpcodeI32Clz, OpcodeI32Ctz, OpcodeI32Popcnt:
649 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
650 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
651 }
652 valueTypeStack.push(ValueTypeI32)
653 case OpcodeI32Add, OpcodeI32Sub, OpcodeI32Mul, OpcodeI32DivS,
654 OpcodeI32DivU, OpcodeI32RemS, OpcodeI32RemU, OpcodeI32And,
655 OpcodeI32Or, OpcodeI32Xor, OpcodeI32Shl, OpcodeI32ShrS,
656 OpcodeI32ShrU, OpcodeI32Rotl, OpcodeI32Rotr:
657 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
658 return fmt.Errorf("cannot pop the 1st operand for %s: %v", InstructionName(op), err)
659 }
660 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
661 return fmt.Errorf("cannot pop the 2nd operand for %s: %v", InstructionName(op), err)
662 }
663 valueTypeStack.push(ValueTypeI32)
664 case OpcodeI64Clz, OpcodeI64Ctz, OpcodeI64Popcnt:
665 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
666 return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
667 }
668 valueTypeStack.push(ValueTypeI64)
669 case OpcodeI64Add, OpcodeI64Sub, OpcodeI64Mul, OpcodeI64DivS,
670 OpcodeI64DivU, OpcodeI64RemS, OpcodeI64RemU, OpcodeI64And,
671 OpcodeI64Or, OpcodeI64Xor, OpcodeI64Shl, OpcodeI64ShrS,
672 OpcodeI64ShrU, OpcodeI64Rotl, OpcodeI64Rotr:
673 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
674 return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
675 }
676 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
677 return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
678 }
679 valueTypeStack.push(ValueTypeI64)
680 case OpcodeF32Abs, OpcodeF32Neg, OpcodeF32Ceil,
681 OpcodeF32Floor, OpcodeF32Trunc, OpcodeF32Nearest,
682 OpcodeF32Sqrt:
683 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
684 return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
685 }
686 valueTypeStack.push(ValueTypeF32)
687 case OpcodeF32Add, OpcodeF32Sub, OpcodeF32Mul,
688 OpcodeF32Div, OpcodeF32Min, OpcodeF32Max,
689 OpcodeF32Copysign:
690 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
691 return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
692 }
693 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
694 return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
695 }
696 valueTypeStack.push(ValueTypeF32)
697 case OpcodeF64Abs, OpcodeF64Neg, OpcodeF64Ceil,
698 OpcodeF64Floor, OpcodeF64Trunc, OpcodeF64Nearest,
699 OpcodeF64Sqrt:
700 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
701 return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
702 }
703 valueTypeStack.push(ValueTypeF64)
704 case OpcodeF64Add, OpcodeF64Sub, OpcodeF64Mul,
705 OpcodeF64Div, OpcodeF64Min, OpcodeF64Max,
706 OpcodeF64Copysign:
707 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
708 return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
709 }
710 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
711 return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
712 }
713 valueTypeStack.push(ValueTypeF64)
714 case OpcodeI32WrapI64:
715 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
716 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32WrapI64Name, err)
717 }
718 valueTypeStack.push(ValueTypeI32)
719 case OpcodeI32TruncF32S, OpcodeI32TruncF32U:
720 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
721 return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
722 }
723 valueTypeStack.push(ValueTypeI32)
724 case OpcodeI32TruncF64S, OpcodeI32TruncF64U:
725 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
726 return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
727 }
728 valueTypeStack.push(ValueTypeI32)
729 case OpcodeI64ExtendI32S, OpcodeI64ExtendI32U:
730 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
731 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
732 }
733 valueTypeStack.push(ValueTypeI64)
734 case OpcodeI64TruncF32S, OpcodeI64TruncF32U:
735 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
736 return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
737 }
738 valueTypeStack.push(ValueTypeI64)
739 case OpcodeI64TruncF64S, OpcodeI64TruncF64U:
740 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
741 return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
742 }
743 valueTypeStack.push(ValueTypeI64)
744 case OpcodeF32ConvertI32S, OpcodeF32ConvertI32U:
745 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
746 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
747 }
748 valueTypeStack.push(ValueTypeF32)
749 case OpcodeF32ConvertI64S, OpcodeF32ConvertI64U:
750 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
751 return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
752 }
753 valueTypeStack.push(ValueTypeF32)
754 case OpcodeF32DemoteF64:
755 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
756 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32DemoteF64Name, err)
757 }
758 valueTypeStack.push(ValueTypeF32)
759 case OpcodeF64ConvertI32S, OpcodeF64ConvertI32U:
760 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
761 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
762 }
763 valueTypeStack.push(ValueTypeF64)
764 case OpcodeF64ConvertI64S, OpcodeF64ConvertI64U:
765 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
766 return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
767 }
768 valueTypeStack.push(ValueTypeF64)
769 case OpcodeF64PromoteF32:
770 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
771 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64PromoteF32Name, err)
772 }
773 valueTypeStack.push(ValueTypeF64)
774 case OpcodeI32ReinterpretF32:
775 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
776 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32ReinterpretF32Name, err)
777 }
778 valueTypeStack.push(ValueTypeI32)
779 case OpcodeI64ReinterpretF64:
780 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
781 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64ReinterpretF64Name, err)
782 }
783 valueTypeStack.push(ValueTypeI64)
784 case OpcodeF32ReinterpretI32:
785 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
786 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32ReinterpretI32Name, err)
787 }
788 valueTypeStack.push(ValueTypeF32)
789 case OpcodeF64ReinterpretI64:
790 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
791 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64ReinterpretI64Name, err)
792 }
793 valueTypeStack.push(ValueTypeF64)
794 case OpcodeI32Extend8S, OpcodeI32Extend16S:
795 if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
796 return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
797 }
798 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
799 return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
800 }
801 valueTypeStack.push(ValueTypeI32)
802 case OpcodeI64Extend8S, OpcodeI64Extend16S, OpcodeI64Extend32S:
803 if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
804 return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
805 }
806 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
807 return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
808 }
809 valueTypeStack.push(ValueTypeI64)
810 default:
811 return fmt.Errorf("invalid numeric instruction 0x%x", op)
812 }
813 } else if op >= OpcodeRefNull && op <= OpcodeRefFunc {
814 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
815 return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
816 }
817 switch op {
818 case OpcodeRefNull:
819 pc++
820 switch reftype := body[pc]; reftype {
821 case ValueTypeExternref:
822 valueTypeStack.push(ValueTypeExternref)
823 case ValueTypeFuncref:
824 valueTypeStack.push(ValueTypeFuncref)
825 default:
826 return fmt.Errorf("unknown type for ref.null: 0x%x", reftype)
827 }
828 case OpcodeRefIsNull:
829 tp, err := valueTypeStack.pop()
830 if err != nil {
831 return fmt.Errorf("cannot pop the operand for ref.is_null: %v", err)
832 } else if !isReferenceValueType(tp) && tp != valueTypeUnknown {
833 return fmt.Errorf("type mismatch: expected reference type but was %s", ValueTypeName(tp))
834 }
835 valueTypeStack.push(ValueTypeI32)
836 case OpcodeRefFunc:
837 pc++
838 index, num, err := leb128.LoadUint32(body[pc:])
839 if err != nil {
840 return fmt.Errorf("failed to read function index for ref.func: %v", err)
841 }
842 if _, ok := declaredFunctionIndexes[index]; !ok {
843 return fmt.Errorf("undeclared function index %d for ref.func", index)
844 }
845 pc += num - 1
846 valueTypeStack.push(ValueTypeFuncref)
847 }
848 } else if op == OpcodeTableGet || op == OpcodeTableSet {
849 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
850 return fmt.Errorf("%s is invalid as %v", InstructionName(op), err)
851 }
852 pc++
853 tableIndex, num, err := leb128.LoadUint32(body[pc:])
854 if err != nil {
855 return fmt.Errorf("read immediate: %v", err)
856 }
857 if tableIndex >= uint32(len(tables)) {
858 return fmt.Errorf("table of index %d not found", tableIndex)
859 }
860
861 refType := tables[tableIndex].Type
862 if op == OpcodeTableGet {
863 if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
864 return fmt.Errorf("cannot pop the operand for table.get: %v", err)
865 }
866 valueTypeStack.push(refType)
867 } else {
868 if err := valueTypeStack.popAndVerifyType(refType); err != nil {
869 return fmt.Errorf("cannot pop the operand for table.set: %v", err)
870 }
871 if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
872 return fmt.Errorf("cannot pop the operand for table.set: %v", err)
873 }
874 }
875 pc += num - 1
876 } else if op == OpcodeMiscPrefix {
877 pc++
878 // A misc opcode is encoded as an unsigned variable 32-bit integer.
879 miscOp32, num, err := leb128.LoadUint32(body[pc:])
880 if err != nil {
881 return fmt.Errorf("failed to read misc opcode: %v", err)
882 }
883 pc += num - 1
884 miscOpcode := byte(miscOp32)
885 // If the misc opcode is beyond byte range, it is highly likely this is an invalid binary, or
886 // it is due to the new opcode from a new proposal. In the latter case, we have to
887 // change the alias type of OpcodeMisc (which is currently byte) to uint32.
888 if uint32(byte(miscOp32)) != miscOp32 {
889 return fmt.Errorf("invalid misc opcode: %#x", miscOp32)
890 }
891 if miscOpcode >= OpcodeMiscI32TruncSatF32S && miscOpcode <= OpcodeMiscI64TruncSatF64U {
892 if err := enabledFeatures.RequireEnabled(api.CoreFeatureNonTrappingFloatToIntConversion); err != nil {
893 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
894 }
895 var inType, outType ValueType
896 switch miscOpcode {
897 case OpcodeMiscI32TruncSatF32S, OpcodeMiscI32TruncSatF32U:
898 inType, outType = ValueTypeF32, ValueTypeI32
899 case OpcodeMiscI32TruncSatF64S, OpcodeMiscI32TruncSatF64U:
900 inType, outType = ValueTypeF64, ValueTypeI32
901 case OpcodeMiscI64TruncSatF32S, OpcodeMiscI64TruncSatF32U:
902 inType, outType = ValueTypeF32, ValueTypeI64
903 case OpcodeMiscI64TruncSatF64S, OpcodeMiscI64TruncSatF64U:
904 inType, outType = ValueTypeF64, ValueTypeI64
905 }
906 if err := valueTypeStack.popAndVerifyType(inType); err != nil {
907 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
908 }
909 valueTypeStack.push(outType)
910 } else if miscOpcode >= OpcodeMiscMemoryInit && miscOpcode <= OpcodeMiscTableCopy {
911 if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
912 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
913 }
914 var params []ValueType
915 // Handle opcodes added in bulk-memory-operations/WebAssembly 2.0.
916 switch miscOpcode {
917 case OpcodeMiscDataDrop:
918 if m.DataCountSection == nil {
919 return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
920 }
921
922 // We need to read the index to the data section.
923 pc++
924 index, num, err := leb128.LoadUint32(body[pc:])
925 if err != nil {
926 return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
927 }
928 if int(index) >= len(m.DataSection) {
929 return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
930 }
931 pc += num - 1
932 case OpcodeMiscMemoryInit, OpcodeMiscMemoryCopy, OpcodeMiscMemoryFill:
933 if memory == nil {
934 return fmt.Errorf("memory must exist for %s", MiscInstructionName(miscOpcode))
935 }
936 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
937
938 if miscOpcode == OpcodeMiscMemoryInit {
939 if m.DataCountSection == nil {
940 return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
941 }
942
943 // We need to read the index to the data section.
944 pc++
945 index, num, err := leb128.LoadUint32(body[pc:])
946 if err != nil {
947 return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
948 }
949 if int(index) >= len(m.DataSection) {
950 return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
951 }
952 pc += num - 1
953 }
954
955 pc++
956 val, num, err := leb128.LoadUint32(body[pc:])
957 if err != nil {
958 return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
959 }
960 if val != 0 || num != 1 {
961 return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
962 }
963 if miscOpcode == OpcodeMiscMemoryCopy {
964 pc++
965 // memory.copy needs two memory index which are reserved as zero.
966 val, num, err := leb128.LoadUint32(body[pc:])
967 if err != nil {
968 return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
969 }
970 if val != 0 || num != 1 {
971 return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
972 }
973 }
974
975 case OpcodeMiscTableInit:
976 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
977 pc++
978 elementIndex, num, err := leb128.LoadUint32(body[pc:])
979 if err != nil {
980 return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
981 }
982 if int(elementIndex) >= len(m.ElementSection) {
983 return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
984 }
985 pc += num
986
987 tableIndex, num, err := leb128.LoadUint32(body[pc:])
988 if err != nil {
989 return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
990 }
991 if tableIndex != 0 {
992 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
993 return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
994 }
995 }
996 if tableIndex >= uint32(len(tables)) {
997 return fmt.Errorf("table of index %d not found", tableIndex)
998 }
999
1000 if m.ElementSection[elementIndex].Type != tables[tableIndex].Type {
1001 return fmt.Errorf("type mismatch for table.init: element type %s does not match table type %s",
1002 RefTypeName(m.ElementSection[elementIndex].Type),
1003 RefTypeName(tables[tableIndex].Type),
1004 )
1005 }
1006 pc += num - 1
1007 case OpcodeMiscElemDrop:
1008 pc++
1009 elementIndex, num, err := leb128.LoadUint32(body[pc:])
1010 if err != nil {
1011 return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
1012 } else if int(elementIndex) >= len(m.ElementSection) {
1013 return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
1014 }
1015 pc += num - 1
1016 case OpcodeMiscTableCopy:
1017 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
1018 pc++
1019
1020 dstTableIndex, num, err := leb128.LoadUint32(body[pc:])
1021 if err != nil {
1022 return fmt.Errorf("failed to read destination table index for %s: %v", MiscInstructionName(miscOpcode), err)
1023 }
1024 if dstTableIndex != 0 {
1025 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1026 return fmt.Errorf("destination table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
1027 }
1028 }
1029 if dstTableIndex >= uint32(len(tables)) {
1030 return fmt.Errorf("table of index %d not found", dstTableIndex)
1031 }
1032 pc += num
1033
1034 srcTableIndex, num, err := leb128.LoadUint32(body[pc:])
1035 if err != nil {
1036 return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
1037 }
1038 if srcTableIndex != 0 {
1039 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1040 return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
1041 }
1042 }
1043 if srcTableIndex >= uint32(len(tables)) {
1044 return fmt.Errorf("table of index %d not found", srcTableIndex)
1045 }
1046
1047 if tables[srcTableIndex].Type != tables[dstTableIndex].Type {
1048 return fmt.Errorf("table type mismatch for table.copy: %s (src) != %s (dst)",
1049 RefTypeName(tables[srcTableIndex].Type), RefTypeName(tables[dstTableIndex].Type))
1050 }
1051
1052 pc += num - 1
1053 }
1054 for _, p := range params {
1055 if err := valueTypeStack.popAndVerifyType(p); err != nil {
1056 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
1057 }
1058 }
1059 } else if miscOpcode >= OpcodeMiscTableGrow && miscOpcode <= OpcodeMiscTableFill {
1060 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1061 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
1062 }
1063
1064 pc++
1065 tableIndex, num, err := leb128.LoadUint32(body[pc:])
1066 if err != nil {
1067 return fmt.Errorf("failed to read table index for %s: %v", MiscInstructionName(miscOpcode), err)
1068 }
1069 if tableIndex >= uint32(len(tables)) {
1070 return fmt.Errorf("table of index %d not found", tableIndex)
1071 }
1072 pc += num - 1
1073
1074 var params, results []ValueType
1075 reftype := tables[tableIndex].Type
1076 if miscOpcode == OpcodeMiscTableGrow {
1077 params = []ValueType{ValueTypeI32, reftype}
1078 results = []ValueType{ValueTypeI32}
1079 } else if miscOpcode == OpcodeMiscTableSize {
1080 results = []ValueType{ValueTypeI32}
1081 } else if miscOpcode == OpcodeMiscTableFill {
1082 params = []ValueType{ValueTypeI32, reftype, ValueTypeI32}
1083 }
1084
1085 for _, p := range params {
1086 if err := valueTypeStack.popAndVerifyType(p); err != nil {
1087 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
1088 }
1089 }
1090 for _, r := range results {
1091 valueTypeStack.push(r)
1092 }
1093 } else {
1094 return fmt.Errorf("unknown misc opcode %#x", miscOpcode)
1095 }
1096 } else if op == OpcodeVecPrefix {
1097 pc++
1098 // Vector instructions come with two bytes where the first byte is always OpcodeVecPrefix,
1099 // and the second byte determines the actual instruction.
1100 vecOpcode := body[pc]
1101 if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil {
1102 return fmt.Errorf("%s invalid as %v", vectorInstructionName[vecOpcode], err)
1103 }
1104
1105 switch vecOpcode {
1106 case OpcodeVecV128Const:
1107 // Read 128-bit = 16 bytes constants
1108 if int(pc+16) >= len(body) {
1109 return fmt.Errorf("cannot read constant vector value for %s", vectorInstructionName[vecOpcode])
1110 }
1111 pc += 16
1112 valueTypeStack.push(ValueTypeV128)
1113 case OpcodeVecV128AnyTrue, OpcodeVecI8x16AllTrue, OpcodeVecI16x8AllTrue, OpcodeVecI32x4AllTrue, OpcodeVecI64x2AllTrue,
1114 OpcodeVecI8x16BitMask, OpcodeVecI16x8BitMask, OpcodeVecI32x4BitMask, OpcodeVecI64x2BitMask:
1115 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1116 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1117 }
1118 valueTypeStack.push(ValueTypeI32)
1119 case OpcodeVecV128Load, OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
1120 OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat,
1121 OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat,
1122 OpcodeVecV128Load32zero, OpcodeVecV128Load64zero:
1123 if memory == nil {
1124 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1125 }
1126 pc++
1127 align, _, read, err := readMemArg(pc, body)
1128 if err != nil {
1129 return err
1130 }
1131 pc += read - 1
1132 var maxAlign uint32
1133 switch vecOpcode {
1134 case OpcodeVecV128Load:
1135 maxAlign = 128 / 8
1136 case OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
1137 OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u:
1138 maxAlign = 64 / 8
1139 case OpcodeVecV128Load8Splat:
1140 maxAlign = 1
1141 case OpcodeVecV128Load16Splat:
1142 maxAlign = 16 / 8
1143 case OpcodeVecV128Load32Splat:
1144 maxAlign = 32 / 8
1145 case OpcodeVecV128Load64Splat:
1146 maxAlign = 64 / 8
1147 case OpcodeVecV128Load32zero:
1148 maxAlign = 32 / 8
1149 case OpcodeVecV128Load64zero:
1150 maxAlign = 64 / 8
1151 }
1152
1153 if 1<<align > maxAlign {
1154 return fmt.Errorf("invalid memory alignment %d for %s", align, VectorInstructionName(vecOpcode))
1155 }
1156 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1157 return fmt.Errorf("cannot pop the operand for %s: %v", VectorInstructionName(vecOpcode), err)
1158 }
1159 valueTypeStack.push(ValueTypeV128)
1160 case OpcodeVecV128Store:
1161 if memory == nil {
1162 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1163 }
1164 pc++
1165 align, _, read, err := readMemArg(pc, body)
1166 if err != nil {
1167 return err
1168 }
1169 pc += read - 1
1170 if 1<<align > 128/8 {
1171 return fmt.Errorf("invalid memory alignment %d for %s", align, OpcodeVecV128StoreName)
1172 }
1173 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1174 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
1175 }
1176 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1177 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
1178 }
1179 case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane:
1180 if memory == nil {
1181 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1182 }
1183 attr := vecLoadLanes[vecOpcode]
1184 pc++
1185 align, _, read, err := readMemArg(pc, body)
1186 if err != nil {
1187 return err
1188 }
1189 if 1<<align > attr.alignMax {
1190 return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
1191 }
1192 pc += read
1193 if pc >= uint64(len(body)) {
1194 return fmt.Errorf("lane for %s not found", OpcodeVecV128Load64LaneName)
1195 }
1196 lane := body[pc]
1197 if lane >= attr.laneCeil {
1198 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1199 }
1200 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1201 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1202 }
1203 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1204 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1205 }
1206 valueTypeStack.push(ValueTypeV128)
1207 case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane:
1208 if memory == nil {
1209 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1210 }
1211 attr := vecStoreLanes[vecOpcode]
1212 pc++
1213 align, _, read, err := readMemArg(pc, body)
1214 if err != nil {
1215 return err
1216 }
1217 if 1<<align > attr.alignMax {
1218 return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
1219 }
1220 pc += read
1221 if pc >= uint64(len(body)) {
1222 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1223 }
1224 lane := body[pc]
1225 if lane >= attr.laneCeil {
1226 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1227 }
1228 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1229 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1230 }
1231 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1232 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1233 }
1234 case OpcodeVecI8x16ExtractLaneS,
1235 OpcodeVecI8x16ExtractLaneU,
1236 OpcodeVecI16x8ExtractLaneS,
1237 OpcodeVecI16x8ExtractLaneU,
1238 OpcodeVecI32x4ExtractLane,
1239 OpcodeVecI64x2ExtractLane,
1240 OpcodeVecF32x4ExtractLane,
1241 OpcodeVecF64x2ExtractLane:
1242 pc++
1243 if pc >= uint64(len(body)) {
1244 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1245 }
1246 attr := vecExtractLanes[vecOpcode]
1247 lane := body[pc]
1248 if lane >= attr.laneCeil {
1249 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1250 }
1251 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1252 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1253 }
1254 valueTypeStack.push(attr.resultType)
1255 case OpcodeVecI8x16ReplaceLane, OpcodeVecI16x8ReplaceLane, OpcodeVecI32x4ReplaceLane,
1256 OpcodeVecI64x2ReplaceLane, OpcodeVecF32x4ReplaceLane, OpcodeVecF64x2ReplaceLane:
1257 pc++
1258 if pc >= uint64(len(body)) {
1259 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1260 }
1261 attr := vecReplaceLanes[vecOpcode]
1262 lane := body[pc]
1263 if lane >= attr.laneCeil {
1264 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1265 }
1266 if err := valueTypeStack.popAndVerifyType(attr.paramType); err != nil {
1267 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1268 }
1269 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1270 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1271 }
1272 valueTypeStack.push(ValueTypeV128)
1273 case OpcodeVecI8x16Splat, OpcodeVecI16x8Splat, OpcodeVecI32x4Splat,
1274 OpcodeVecI64x2Splat, OpcodeVecF32x4Splat, OpcodeVecF64x2Splat:
1275 tp := vecSplatValueTypes[vecOpcode]
1276 if err := valueTypeStack.popAndVerifyType(tp); err != nil {
1277 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1278 }
1279 valueTypeStack.push(ValueTypeV128)
1280 case OpcodeVecI8x16Swizzle, OpcodeVecV128And, OpcodeVecV128Or, OpcodeVecV128Xor, OpcodeVecV128AndNot:
1281 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1282 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1283 }
1284 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1285 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1286 }
1287 valueTypeStack.push(ValueTypeV128)
1288 case OpcodeVecV128Bitselect:
1289 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1290 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1291 }
1292 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1293 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1294 }
1295 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1296 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1297 }
1298 valueTypeStack.push(ValueTypeV128)
1299 case OpcodeVecV128Not:
1300 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1301 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1302 }
1303 valueTypeStack.push(ValueTypeV128)
1304 case OpcodeVecV128i8x16Shuffle:
1305 pc++
1306 if pc+15 >= uint64(len(body)) {
1307 return fmt.Errorf("16 lane indexes for %s not found", vectorInstructionName[vecOpcode])
1308 }
1309 lanes := body[pc : pc+16]
1310 for i, l := range lanes {
1311 if l >= 32 {
1312 return fmt.Errorf("invalid lane index[%d] %d >= %d for %s", i, l, 32, vectorInstructionName[vecOpcode])
1313 }
1314 }
1315 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1316 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1317 }
1318 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1319 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1320 }
1321 valueTypeStack.push(ValueTypeV128)
1322 pc += 15
1323 case OpcodeVecI8x16Shl, OpcodeVecI8x16ShrS, OpcodeVecI8x16ShrU,
1324 OpcodeVecI16x8Shl, OpcodeVecI16x8ShrS, OpcodeVecI16x8ShrU,
1325 OpcodeVecI32x4Shl, OpcodeVecI32x4ShrS, OpcodeVecI32x4ShrU,
1326 OpcodeVecI64x2Shl, OpcodeVecI64x2ShrS, OpcodeVecI64x2ShrU:
1327 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1328 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1329 }
1330 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1331 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1332 }
1333 valueTypeStack.push(ValueTypeV128)
1334 case OpcodeVecI8x16Eq, OpcodeVecI8x16Ne, OpcodeVecI8x16LtS, OpcodeVecI8x16LtU, OpcodeVecI8x16GtS,
1335 OpcodeVecI8x16GtU, OpcodeVecI8x16LeS, OpcodeVecI8x16LeU, OpcodeVecI8x16GeS, OpcodeVecI8x16GeU,
1336 OpcodeVecI16x8Eq, OpcodeVecI16x8Ne, OpcodeVecI16x8LtS, OpcodeVecI16x8LtU, OpcodeVecI16x8GtS,
1337 OpcodeVecI16x8GtU, OpcodeVecI16x8LeS, OpcodeVecI16x8LeU, OpcodeVecI16x8GeS, OpcodeVecI16x8GeU,
1338 OpcodeVecI32x4Eq, OpcodeVecI32x4Ne, OpcodeVecI32x4LtS, OpcodeVecI32x4LtU, OpcodeVecI32x4GtS,
1339 OpcodeVecI32x4GtU, OpcodeVecI32x4LeS, OpcodeVecI32x4LeU, OpcodeVecI32x4GeS, OpcodeVecI32x4GeU,
1340 OpcodeVecI64x2Eq, OpcodeVecI64x2Ne, OpcodeVecI64x2LtS, OpcodeVecI64x2GtS, OpcodeVecI64x2LeS,
1341 OpcodeVecI64x2GeS, OpcodeVecF32x4Eq, OpcodeVecF32x4Ne, OpcodeVecF32x4Lt, OpcodeVecF32x4Gt,
1342 OpcodeVecF32x4Le, OpcodeVecF32x4Ge, OpcodeVecF64x2Eq, OpcodeVecF64x2Ne, OpcodeVecF64x2Lt,
1343 OpcodeVecF64x2Gt, OpcodeVecF64x2Le, OpcodeVecF64x2Ge,
1344 OpcodeVecI32x4DotI16x8S,
1345 OpcodeVecI8x16NarrowI16x8S, OpcodeVecI8x16NarrowI16x8U, OpcodeVecI16x8NarrowI32x4S, OpcodeVecI16x8NarrowI32x4U:
1346 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1347 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1348 }
1349 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1350 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1351 }
1352 valueTypeStack.push(ValueTypeV128)
1353 case OpcodeVecI8x16Neg, OpcodeVecI16x8Neg, OpcodeVecI32x4Neg, OpcodeVecI64x2Neg, OpcodeVecF32x4Neg, OpcodeVecF64x2Neg,
1354 OpcodeVecF32x4Sqrt, OpcodeVecF64x2Sqrt,
1355 OpcodeVecI8x16Abs, OpcodeVecI8x16Popcnt, OpcodeVecI16x8Abs, OpcodeVecI32x4Abs, OpcodeVecI64x2Abs,
1356 OpcodeVecF32x4Abs, OpcodeVecF64x2Abs,
1357 OpcodeVecF32x4Ceil, OpcodeVecF32x4Floor, OpcodeVecF32x4Trunc, OpcodeVecF32x4Nearest,
1358 OpcodeVecF64x2Ceil, OpcodeVecF64x2Floor, OpcodeVecF64x2Trunc, OpcodeVecF64x2Nearest,
1359 OpcodeVecI16x8ExtendLowI8x16S, OpcodeVecI16x8ExtendHighI8x16S, OpcodeVecI16x8ExtendLowI8x16U, OpcodeVecI16x8ExtendHighI8x16U,
1360 OpcodeVecI32x4ExtendLowI16x8S, OpcodeVecI32x4ExtendHighI16x8S, OpcodeVecI32x4ExtendLowI16x8U, OpcodeVecI32x4ExtendHighI16x8U,
1361 OpcodeVecI64x2ExtendLowI32x4S, OpcodeVecI64x2ExtendHighI32x4S, OpcodeVecI64x2ExtendLowI32x4U, OpcodeVecI64x2ExtendHighI32x4U,
1362 OpcodeVecI16x8ExtaddPairwiseI8x16S, OpcodeVecI16x8ExtaddPairwiseI8x16U,
1363 OpcodeVecI32x4ExtaddPairwiseI16x8S, OpcodeVecI32x4ExtaddPairwiseI16x8U,
1364 OpcodeVecF64x2PromoteLowF32x4Zero, OpcodeVecF32x4DemoteF64x2Zero,
1365 OpcodeVecF32x4ConvertI32x4S, OpcodeVecF32x4ConvertI32x4U,
1366 OpcodeVecF64x2ConvertLowI32x4S, OpcodeVecF64x2ConvertLowI32x4U,
1367 OpcodeVecI32x4TruncSatF32x4S, OpcodeVecI32x4TruncSatF32x4U, OpcodeVecI32x4TruncSatF64x2SZero, OpcodeVecI32x4TruncSatF64x2UZero:
1368 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1369 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1370 }
1371 valueTypeStack.push(ValueTypeV128)
1372
1373 case OpcodeVecI8x16Add, OpcodeVecI8x16AddSatS, OpcodeVecI8x16AddSatU, OpcodeVecI8x16Sub, OpcodeVecI8x16SubSatS, OpcodeVecI8x16SubSatU,
1374 OpcodeVecI16x8Add, OpcodeVecI16x8AddSatS, OpcodeVecI16x8AddSatU, OpcodeVecI16x8Sub, OpcodeVecI16x8SubSatS, OpcodeVecI16x8SubSatU, OpcodeVecI16x8Mul,
1375 OpcodeVecI32x4Add, OpcodeVecI32x4Sub, OpcodeVecI32x4Mul,
1376 OpcodeVecI64x2Add, OpcodeVecI64x2Sub, OpcodeVecI64x2Mul,
1377 OpcodeVecF32x4Add, OpcodeVecF32x4Sub, OpcodeVecF32x4Mul, OpcodeVecF32x4Div,
1378 OpcodeVecF64x2Add, OpcodeVecF64x2Sub, OpcodeVecF64x2Mul, OpcodeVecF64x2Div,
1379 OpcodeVecI8x16MinS, OpcodeVecI8x16MinU, OpcodeVecI8x16MaxS, OpcodeVecI8x16MaxU,
1380 OpcodeVecI8x16AvgrU,
1381 OpcodeVecI16x8MinS, OpcodeVecI16x8MinU, OpcodeVecI16x8MaxS, OpcodeVecI16x8MaxU,
1382 OpcodeVecI16x8AvgrU,
1383 OpcodeVecI32x4MinS, OpcodeVecI32x4MinU, OpcodeVecI32x4MaxS, OpcodeVecI32x4MaxU,
1384 OpcodeVecF32x4Min, OpcodeVecF32x4Max, OpcodeVecF64x2Min, OpcodeVecF64x2Max,
1385 OpcodeVecF32x4Pmin, OpcodeVecF32x4Pmax, OpcodeVecF64x2Pmin, OpcodeVecF64x2Pmax,
1386 OpcodeVecI16x8Q15mulrSatS,
1387 OpcodeVecI16x8ExtMulLowI8x16S, OpcodeVecI16x8ExtMulHighI8x16S, OpcodeVecI16x8ExtMulLowI8x16U, OpcodeVecI16x8ExtMulHighI8x16U,
1388 OpcodeVecI32x4ExtMulLowI16x8S, OpcodeVecI32x4ExtMulHighI16x8S, OpcodeVecI32x4ExtMulLowI16x8U, OpcodeVecI32x4ExtMulHighI16x8U,
1389 OpcodeVecI64x2ExtMulLowI32x4S, OpcodeVecI64x2ExtMulHighI32x4S, OpcodeVecI64x2ExtMulLowI32x4U, OpcodeVecI64x2ExtMulHighI32x4U:
1390 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1391 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1392 }
1393 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1394 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1395 }
1396 valueTypeStack.push(ValueTypeV128)
1397 default:
1398 return fmt.Errorf("unknown SIMD instruction %s", vectorInstructionName[vecOpcode])
1399 }
1400 } else if op == OpcodeBlock {
1401 br.Reset(body[pc+1:])
1402 bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1403 if err != nil {
1404 return fmt.Errorf("read block: %w", err)
1405 }
1406 controlBlockStack.push(pc, 0, 0, bt, num, 0)
1407 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1408 return err
1409 }
1410 // Plus we have to push any block params again.
1411 for _, p := range bt.Params {
1412 valueTypeStack.push(p)
1413 }
1414 valueTypeStack.pushStackLimit(len(bt.Params))
1415 pc += num
1416 } else if op == OpcodeAtomicPrefix {
1417 pc++
1418 // Atomic instructions come with two bytes where the first byte is always OpcodeAtomicPrefix,
1419 // and the second byte determines the actual instruction.
1420 atomicOpcode := body[pc]
1421 if err := enabledFeatures.RequireEnabled(experimental.CoreFeaturesThreads); err != nil {
1422 return fmt.Errorf("%s invalid as %v", atomicInstructionName[atomicOpcode], err)
1423 }
1424 pc++
1425
1426 if atomicOpcode == OpcodeAtomicFence {
1427 // No memory requirement and no arguments or return, however the immediate byte value must be 0.
1428 imm := body[pc]
1429 if imm != 0x0 {
1430 return fmt.Errorf("invalid immediate value for %s", AtomicInstructionName(atomicOpcode))
1431 }
1432 continue
1433 }
1434
1435 // All atomic operations except fence (checked above) require memory
1436 if memory == nil {
1437 return fmt.Errorf("memory must exist for %s", AtomicInstructionName(atomicOpcode))
1438 }
1439 align, _, read, err := readMemArg(pc, body)
1440 if err != nil {
1441 return err
1442 }
1443 pc += read - 1
1444 switch atomicOpcode {
1445 case OpcodeAtomicMemoryNotify:
1446 if 1<<align > 32/8 {
1447 return fmt.Errorf("invalid memory alignment")
1448 }
1449 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1450 return err
1451 }
1452 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1453 return err
1454 }
1455 valueTypeStack.push(ValueTypeI32)
1456 case OpcodeAtomicMemoryWait32:
1457 if 1<<align > 32/8 {
1458 return fmt.Errorf("invalid memory alignment")
1459 }
1460 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1461 return err
1462 }
1463 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1464 return err
1465 }
1466 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1467 return err
1468 }
1469 valueTypeStack.push(ValueTypeI32)
1470 case OpcodeAtomicMemoryWait64:
1471 if 1<<align > 64/8 {
1472 return fmt.Errorf("invalid memory alignment")
1473 }
1474 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1475 return err
1476 }
1477 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1478 return err
1479 }
1480 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1481 return err
1482 }
1483 valueTypeStack.push(ValueTypeI32)
1484 case OpcodeAtomicI32Load:
1485 if 1<<align > 32/8 {
1486 return fmt.Errorf("invalid memory alignment")
1487 }
1488 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1489 return err
1490 }
1491 valueTypeStack.push(ValueTypeI32)
1492 case OpcodeAtomicI64Load:
1493 if 1<<align > 64/8 {
1494 return fmt.Errorf("invalid memory alignment")
1495 }
1496 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1497 return err
1498 }
1499 valueTypeStack.push(ValueTypeI64)
1500 case OpcodeAtomicI32Load8U:
1501 if 1<<align != 1 {
1502 return fmt.Errorf("invalid memory alignment")
1503 }
1504 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1505 return err
1506 }
1507 valueTypeStack.push(ValueTypeI32)
1508 case OpcodeAtomicI32Load16U:
1509 if 1<<align != 16/8 {
1510 return fmt.Errorf("invalid memory alignment")
1511 }
1512 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1513 return err
1514 }
1515 valueTypeStack.push(ValueTypeI32)
1516 case OpcodeAtomicI64Load8U:
1517 if 1<<align != 1 {
1518 return fmt.Errorf("invalid memory alignment")
1519 }
1520 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1521 return err
1522 }
1523 valueTypeStack.push(ValueTypeI64)
1524 case OpcodeAtomicI64Load16U:
1525 if 1<<align > 16/8 {
1526 return fmt.Errorf("invalid memory alignment")
1527 }
1528 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1529 return err
1530 }
1531 valueTypeStack.push(ValueTypeI64)
1532 case OpcodeAtomicI64Load32U:
1533 if 1<<align > 32/8 {
1534 return fmt.Errorf("invalid memory alignment")
1535 }
1536 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1537 return err
1538 }
1539 valueTypeStack.push(ValueTypeI64)
1540 case OpcodeAtomicI32Store:
1541 if 1<<align > 32/8 {
1542 return fmt.Errorf("invalid memory alignment")
1543 }
1544 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1545 return err
1546 }
1547 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1548 return err
1549 }
1550 case OpcodeAtomicI64Store:
1551 if 1<<align > 64/8 {
1552 return fmt.Errorf("invalid memory alignment")
1553 }
1554 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1555 return err
1556 }
1557 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1558 return err
1559 }
1560 case OpcodeAtomicI32Store8:
1561 if 1<<align > 1 {
1562 return fmt.Errorf("invalid memory alignment")
1563 }
1564 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1565 return err
1566 }
1567 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1568 return err
1569 }
1570 case OpcodeAtomicI32Store16:
1571 if 1<<align > 16/8 {
1572 return fmt.Errorf("invalid memory alignment")
1573 }
1574 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1575 return err
1576 }
1577 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1578 return err
1579 }
1580 case OpcodeAtomicI64Store8:
1581 if 1<<align > 1 {
1582 return fmt.Errorf("invalid memory alignment")
1583 }
1584 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1585 return err
1586 }
1587 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1588 return err
1589 }
1590 case OpcodeAtomicI64Store16:
1591 if 1<<align > 16/8 {
1592 return fmt.Errorf("invalid memory alignment")
1593 }
1594 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1595 return err
1596 }
1597 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1598 return err
1599 }
1600 case OpcodeAtomicI64Store32:
1601 if 1<<align > 32/8 {
1602 return fmt.Errorf("invalid memory alignment")
1603 }
1604 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1605 return err
1606 }
1607 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1608 return err
1609 }
1610 case OpcodeAtomicI32RmwAdd, OpcodeAtomicI32RmwSub, OpcodeAtomicI32RmwAnd, OpcodeAtomicI32RmwOr, OpcodeAtomicI32RmwXor, OpcodeAtomicI32RmwXchg:
1611 if 1<<align > 32/8 {
1612 return fmt.Errorf("invalid memory alignment")
1613 }
1614 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1615 return err
1616 }
1617 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1618 return err
1619 }
1620 valueTypeStack.push(ValueTypeI32)
1621 case OpcodeAtomicI32Rmw8AddU, OpcodeAtomicI32Rmw8SubU, OpcodeAtomicI32Rmw8AndU, OpcodeAtomicI32Rmw8OrU, OpcodeAtomicI32Rmw8XorU, OpcodeAtomicI32Rmw8XchgU:
1622 if 1<<align > 1 {
1623 return fmt.Errorf("invalid memory alignment")
1624 }
1625 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1626 return err
1627 }
1628 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1629 return err
1630 }
1631 valueTypeStack.push(ValueTypeI32)
1632 case OpcodeAtomicI32Rmw16AddU, OpcodeAtomicI32Rmw16SubU, OpcodeAtomicI32Rmw16AndU, OpcodeAtomicI32Rmw16OrU, OpcodeAtomicI32Rmw16XorU, OpcodeAtomicI32Rmw16XchgU:
1633 if 1<<align > 16/8 {
1634 return fmt.Errorf("invalid memory alignment")
1635 }
1636 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1637 return err
1638 }
1639 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1640 return err
1641 }
1642 valueTypeStack.push(ValueTypeI32)
1643 case OpcodeAtomicI64RmwAdd, OpcodeAtomicI64RmwSub, OpcodeAtomicI64RmwAnd, OpcodeAtomicI64RmwOr, OpcodeAtomicI64RmwXor, OpcodeAtomicI64RmwXchg:
1644 if 1<<align > 64/8 {
1645 return fmt.Errorf("invalid memory alignment")
1646 }
1647 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1648 return err
1649 }
1650 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1651 return err
1652 }
1653 valueTypeStack.push(ValueTypeI64)
1654 case OpcodeAtomicI64Rmw8AddU, OpcodeAtomicI64Rmw8SubU, OpcodeAtomicI64Rmw8AndU, OpcodeAtomicI64Rmw8OrU, OpcodeAtomicI64Rmw8XorU, OpcodeAtomicI64Rmw8XchgU:
1655 if 1<<align > 1 {
1656 return fmt.Errorf("invalid memory alignment")
1657 }
1658 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1659 return err
1660 }
1661 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1662 return err
1663 }
1664 valueTypeStack.push(ValueTypeI64)
1665 case OpcodeAtomicI64Rmw16AddU, OpcodeAtomicI64Rmw16SubU, OpcodeAtomicI64Rmw16AndU, OpcodeAtomicI64Rmw16OrU, OpcodeAtomicI64Rmw16XorU, OpcodeAtomicI64Rmw16XchgU:
1666 if 1<<align > 16/8 {
1667 return fmt.Errorf("invalid memory alignment")
1668 }
1669 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1670 return err
1671 }
1672 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1673 return err
1674 }
1675 valueTypeStack.push(ValueTypeI64)
1676 case OpcodeAtomicI64Rmw32AddU, OpcodeAtomicI64Rmw32SubU, OpcodeAtomicI64Rmw32AndU, OpcodeAtomicI64Rmw32OrU, OpcodeAtomicI64Rmw32XorU, OpcodeAtomicI64Rmw32XchgU:
1677 if 1<<align > 32/8 {
1678 return fmt.Errorf("invalid memory alignment")
1679 }
1680 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1681 return err
1682 }
1683 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1684 return err
1685 }
1686 valueTypeStack.push(ValueTypeI64)
1687 case OpcodeAtomicI32RmwCmpxchg:
1688 if 1<<align > 32/8 {
1689 return fmt.Errorf("invalid memory alignment")
1690 }
1691 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1692 return err
1693 }
1694 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1695 return err
1696 }
1697 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1698 return err
1699 }
1700 valueTypeStack.push(ValueTypeI32)
1701 case OpcodeAtomicI32Rmw8CmpxchgU:
1702 if 1<<align > 1 {
1703 return fmt.Errorf("invalid memory alignment")
1704 }
1705 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1706 return err
1707 }
1708 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1709 return err
1710 }
1711 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1712 return err
1713 }
1714 valueTypeStack.push(ValueTypeI32)
1715 case OpcodeAtomicI32Rmw16CmpxchgU:
1716 if 1<<align > 16/8 {
1717 return fmt.Errorf("invalid memory alignment")
1718 }
1719 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1720 return err
1721 }
1722 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1723 return err
1724 }
1725 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1726 return err
1727 }
1728 valueTypeStack.push(ValueTypeI32)
1729 case OpcodeAtomicI64RmwCmpxchg:
1730 if 1<<align > 64/8 {
1731 return fmt.Errorf("invalid memory alignment")
1732 }
1733 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1734 return err
1735 }
1736 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1737 return err
1738 }
1739 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1740 return err
1741 }
1742 valueTypeStack.push(ValueTypeI64)
1743 case OpcodeAtomicI64Rmw8CmpxchgU:
1744 if 1<<align > 1 {
1745 return fmt.Errorf("invalid memory alignment")
1746 }
1747 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1748 return err
1749 }
1750 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1751 return err
1752 }
1753 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1754 return err
1755 }
1756 valueTypeStack.push(ValueTypeI64)
1757 case OpcodeAtomicI64Rmw16CmpxchgU:
1758 if 1<<align > 16/8 {
1759 return fmt.Errorf("invalid memory alignment")
1760 }
1761 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1762 return err
1763 }
1764 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1765 return err
1766 }
1767 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1768 return err
1769 }
1770 valueTypeStack.push(ValueTypeI64)
1771 case OpcodeAtomicI64Rmw32CmpxchgU:
1772 if 1<<align > 32/8 {
1773 return fmt.Errorf("invalid memory alignment")
1774 }
1775 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1776 return err
1777 }
1778 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
1779 return err
1780 }
1781 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1782 return err
1783 }
1784 valueTypeStack.push(ValueTypeI64)
1785 default:
1786 return fmt.Errorf("invalid atomic opcode: 0x%x", atomicOpcode)
1787 }
1788 } else if op == OpcodeLoop {
1789 br.Reset(body[pc+1:])
1790 bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1791 if err != nil {
1792 return fmt.Errorf("read block: %w", err)
1793 }
1794 controlBlockStack.push(pc, 0, 0, bt, num, op)
1795 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1796 return err
1797 }
1798 // Plus we have to push any block params again.
1799 for _, p := range bt.Params {
1800 valueTypeStack.push(p)
1801 }
1802 valueTypeStack.pushStackLimit(len(bt.Params))
1803 pc += num
1804 } else if op == OpcodeIf {
1805 br.Reset(body[pc+1:])
1806 bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1807 if err != nil {
1808 return fmt.Errorf("read block: %w", err)
1809 }
1810 controlBlockStack.push(pc, 0, 0, bt, num, op)
1811 if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1812 return fmt.Errorf("cannot pop the operand for 'if': %v", err)
1813 }
1814 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1815 return err
1816 }
1817 // Plus we have to push any block params again.
1818 for _, p := range bt.Params {
1819 valueTypeStack.push(p)
1820 }
1821 valueTypeStack.pushStackLimit(len(bt.Params))
1822 pc += num
1823 } else if op == OpcodeElse {
1824 bl := &controlBlockStack.stack[len(controlBlockStack.stack)-1]
1825 if bl.op != OpcodeIf {
1826 return fmt.Errorf("else instruction must be used in if block: %#x", pc)
1827 }
1828 bl.op = OpcodeElse
1829 bl.elseAt = pc
1830 // Check the type soundness of the instructions *before* entering this else Op.
1831 if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil {
1832 return err
1833 }
1834 // Before entering instructions inside else, we pop all the values pushed by then block.
1835 valueTypeStack.resetAtStackLimit()
1836 // Plus we have to push any block params again.
1837 for _, p := range bl.blockType.Params {
1838 valueTypeStack.push(p)
1839 }
1840 } else if op == OpcodeEnd {
1841 bl := controlBlockStack.pop()
1842 bl.endAt = pc
1843
1844 // OpcodeEnd can end a block or the function itself. Check to see what it is:
1845
1846 ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt
1847 if ifMissingElse {
1848 // If this is the end of block without else, the number of block's results and params must be same.
1849 // Otherwise, the value stack would result in the inconsistent state at runtime.
1850 if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) {
1851 return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results)
1852 }
1853 // -1 skips else, to handle if block without else properly.
1854 bl.elseAt = bl.endAt - 1
1855 }
1856
1857 // Determine the block context
1858 ctx := "" // the outer-most block: the function return
1859 if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 {
1860 ctx = OpcodeElseName
1861 } else if bl.op != 0 {
1862 ctx = InstructionName(bl.op)
1863 }
1864
1865 // Check return types match
1866 if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil {
1867 return err
1868 }
1869
1870 // Put the result types at the end after resetting at the stack limit
1871 // since we might have Any type between the limit and the current top.
1872 valueTypeStack.resetAtStackLimit()
1873 for _, exp := range bl.blockType.Results {
1874 valueTypeStack.push(exp)
1875 }
1876 // We exit if/loop/block, so reset the constraints on the stack manipulation
1877 // on values previously pushed by outer blocks.
1878 valueTypeStack.popStackLimit()
1879 } else if op == OpcodeReturn {
1880 // Same formatting as OpcodeEnd on the outer-most block
1881 if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil {
1882 return err
1883 }
1884 // return instruction is stack-polymorphic.
1885 valueTypeStack.unreachable()
1886 } else if op == OpcodeDrop {
1887 _, err := valueTypeStack.pop()
1888 if err != nil {
1889 return fmt.Errorf("invalid drop: %v", err)
1890 }
1891 } else if op == OpcodeSelect || op == OpcodeTypedSelect {
1892 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1893 return fmt.Errorf("type mismatch on 3rd select operand: %v", err)
1894 }
1895 v1, err := valueTypeStack.pop()
1896 if err != nil {
1897 return fmt.Errorf("invalid select: %v", err)
1898 }
1899 v2, err := valueTypeStack.pop()
1900 if err != nil {
1901 return fmt.Errorf("invalid select: %v", err)
1902 }
1903
1904 if op == OpcodeTypedSelect {
1905 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1906 return fmt.Errorf("%s is invalid as %w", InstructionName(op), err)
1907 }
1908 pc++
1909 if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 {
1910 return fmt.Errorf("too many type immediates for %s", InstructionName(op))
1911 }
1912 pc++
1913 tp := body[pc]
1914 if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 &&
1915 tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 {
1916 return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName)
1917 }
1918 } else if isReferenceValueType(v1) || isReferenceValueType(v2) {
1919 return fmt.Errorf("reference types cannot be used for non typed select instruction")
1920 }
1921
1922 if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown {
1923 return fmt.Errorf("type mismatch on 1st and 2nd select operands")
1924 }
1925 if v1 == valueTypeUnknown {
1926 valueTypeStack.push(v2)
1927 } else {
1928 valueTypeStack.push(v1)
1929 }
1930 } else if op == OpcodeUnreachable {
1931 // unreachable instruction is stack-polymorphic.
1932 valueTypeStack.unreachable()
1933 } else if op == OpcodeNop {
1934 } else {
1935 return fmt.Errorf("invalid instruction 0x%x", op)
1936 }
1937 }
1938
1939 if len(controlBlockStack.stack) > 0 {
1940 return fmt.Errorf("ill-nested block exists")
1941 }
1942 if valueTypeStack.maximumStackPointer > maxStackValues {
1943 return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues)
1944 }
1945 return nil
1946}
1947
1948var vecExtractLanes = [...]struct {
1949 laneCeil byte
1950 resultType ValueType
1951}{
1952 OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32},
1953 OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32},
1954 OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32},
1955 OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32},
1956 OpcodeVecI32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeI32},
1957 OpcodeVecI64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeI64},
1958 OpcodeVecF32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeF32},
1959 OpcodeVecF64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeF64},
1960}
1961
1962var vecReplaceLanes = [...]struct {
1963 laneCeil byte
1964 paramType ValueType
1965}{
1966 OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32},
1967 OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32},
1968 OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32},
1969 OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64},
1970 OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32},
1971 OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64},
1972}
1973
1974var vecStoreLanes = [...]struct {
1975 alignMax uint32
1976 laneCeil byte
1977}{
1978 OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
1979 OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
1980 OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
1981 OpcodeVecV128Store8Lane: {alignMax: 1, laneCeil: 128 / 8},
1982}
1983
1984var vecLoadLanes = [...]struct {
1985 alignMax uint32
1986 laneCeil byte
1987}{
1988 OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
1989 OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
1990 OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
1991 OpcodeVecV128Load8Lane: {alignMax: 1, laneCeil: 128 / 8},
1992}
1993
1994var vecSplatValueTypes = [...]ValueType{
1995 OpcodeVecI8x16Splat: ValueTypeI32,
1996 OpcodeVecI16x8Splat: ValueTypeI32,
1997 OpcodeVecI32x4Splat: ValueTypeI32,
1998 OpcodeVecI64x2Splat: ValueTypeI64,
1999 OpcodeVecF32x4Splat: ValueTypeF32,
2000 OpcodeVecF64x2Splat: ValueTypeF64,
2001}
2002
2003type stacks struct {
2004 vs valueTypeStack
2005 cs controlBlockStack
2006 // ls is the label slice that is reused for each br_table instruction.
2007 ls []uint32
2008}
2009
2010func (sts *stacks) reset(functionType *FunctionType) {
2011 // Reset valueStack for reuse.
2012 sts.vs.stack = sts.vs.stack[:0]
2013 sts.vs.stackLimits = sts.vs.stackLimits[:0]
2014 sts.vs.maximumStackPointer = 0
2015 sts.cs.stack = sts.cs.stack[:0]
2016 sts.cs.stack = append(sts.cs.stack, controlBlock{blockType: functionType})
2017 sts.ls = sts.ls[:0]
2018}
2019
2020type controlBlockStack struct {
2021 stack []controlBlock
2022}
2023
2024func (s *controlBlockStack) pop() *controlBlock {
2025 tail := len(s.stack) - 1
2026 ret := &s.stack[tail]
2027 s.stack = s.stack[:tail]
2028 return ret
2029}
2030
2031func (s *controlBlockStack) push(startAt, elseAt, endAt uint64, blockType *FunctionType, blockTypeBytes uint64, op Opcode) {
2032 s.stack = append(s.stack, controlBlock{
2033 startAt: startAt,
2034 elseAt: elseAt,
2035 endAt: endAt,
2036 blockType: blockType,
2037 blockTypeBytes: blockTypeBytes,
2038 op: op,
2039 })
2040}
2041
2042type valueTypeStack struct {
2043 stack []ValueType
2044 stackLimits []int
2045 maximumStackPointer int
2046 // requireStackValuesTmp is used in requireStackValues function to reduce the allocation.
2047 requireStackValuesTmp []ValueType
2048}
2049
2050// Only used in the analyzeFunction below.
2051const valueTypeUnknown = ValueType(0xFF)
2052
2053func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) {
2054 if len(s.stackLimits) > 0 {
2055 limit = s.stackLimits[len(s.stackLimits)-1]
2056 }
2057 stackLen := len(s.stack)
2058 if stackLen <= limit {
2059 return
2060 } else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown {
2061 vt = valueTypeUnknown
2062 ok = true
2063 return
2064 } else {
2065 vt = s.stack[stackLen-1]
2066 s.stack = s.stack[:stackLen-1]
2067 ok = true
2068 return
2069 }
2070}
2071
2072func (s *valueTypeStack) pop() (ValueType, error) {
2073 if vt, limit, ok := s.tryPop(); ok {
2074 return vt, nil
2075 } else {
2076 return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit)
2077 }
2078}
2079
2080// popAndVerifyType returns an error if the stack value is unexpected.
2081func (s *valueTypeStack) popAndVerifyType(expected ValueType) error {
2082 have, _, ok := s.tryPop()
2083 if !ok {
2084 return fmt.Errorf("%s missing", ValueTypeName(expected))
2085 }
2086 if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown {
2087 return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have))
2088 }
2089 return nil
2090}
2091
2092func (s *valueTypeStack) push(v ValueType) {
2093 s.stack = append(s.stack, v)
2094 if sp := len(s.stack); sp > s.maximumStackPointer {
2095 s.maximumStackPointer = sp
2096 }
2097}
2098
2099func (s *valueTypeStack) unreachable() {
2100 s.resetAtStackLimit()
2101 s.stack = append(s.stack, valueTypeUnknown)
2102}
2103
2104func (s *valueTypeStack) resetAtStackLimit() {
2105 if len(s.stackLimits) != 0 {
2106 s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]]
2107 } else {
2108 s.stack = s.stack[:0]
2109 }
2110}
2111
2112func (s *valueTypeStack) popStackLimit() {
2113 if len(s.stackLimits) != 0 {
2114 s.stackLimits = s.stackLimits[:len(s.stackLimits)-1]
2115 }
2116}
2117
2118// pushStackLimit pushes the control frame's bottom of the stack.
2119func (s *valueTypeStack) pushStackLimit(params int) {
2120 limit := len(s.stack) - params
2121 s.stackLimits = append(s.stackLimits, limit)
2122}
2123
2124func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error {
2125 return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit)
2126}
2127
2128func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error {
2129 return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit)
2130}
2131
2132func (s *valueTypeStack) requireStackValues(
2133 isParam bool,
2134 context string,
2135 want []ValueType,
2136 checkAboveLimit bool,
2137) error {
2138 limit := 0
2139 if len(s.stackLimits) > 0 {
2140 limit = s.stackLimits[len(s.stackLimits)-1]
2141 }
2142 // Iterate backwards as we are comparing the desired slice against stack value types.
2143 countWanted := len(want)
2144
2145 // First, check if there are enough values on the stack.
2146 s.requireStackValuesTmp = s.requireStackValuesTmp[:0]
2147 for i := countWanted - 1; i >= 0; i-- {
2148 popped, _, ok := s.tryPop()
2149 if !ok {
2150 if len(s.requireStackValuesTmp) > len(want) {
2151 return typeCountError(isParam, context, s.requireStackValuesTmp, want)
2152 }
2153 return typeCountError(isParam, context, s.requireStackValuesTmp, want)
2154 }
2155 s.requireStackValuesTmp = append(s.requireStackValuesTmp, popped)
2156 }
2157
2158 // Now, check if there are too many values.
2159 if checkAboveLimit {
2160 if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) {
2161 return typeCountError(isParam, context, append(s.stack, want...), want)
2162 }
2163 }
2164
2165 // Finally, check the types of the values:
2166 for i, v := range s.requireStackValuesTmp {
2167 nextWant := want[countWanted-i-1] // have is in reverse order (stack)
2168 if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown {
2169 return typeMismatchError(isParam, context, v, nextWant, i)
2170 }
2171 }
2172 return nil
2173}
2174
2175// typeMismatchError returns an error similar to go compiler's error on type mismatch.
2176func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error {
2177 var ret strings.Builder
2178 ret.WriteString("cannot use ")
2179 ret.WriteString(ValueTypeName(have))
2180 if context != "" {
2181 ret.WriteString(" in ")
2182 ret.WriteString(context)
2183 ret.WriteString(" block")
2184 }
2185 if isParam {
2186 ret.WriteString(" as param")
2187 } else {
2188 ret.WriteString(" as result")
2189 }
2190 ret.WriteString("[")
2191 ret.WriteString(strconv.Itoa(i))
2192 ret.WriteString("] type ")
2193 ret.WriteString(ValueTypeName(want))
2194 return errors.New(ret.String())
2195}
2196
2197// typeCountError returns an error similar to go compiler's error on type count mismatch.
2198func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error {
2199 var ret strings.Builder
2200 if len(have) > len(want) {
2201 ret.WriteString("too many ")
2202 } else {
2203 ret.WriteString("not enough ")
2204 }
2205 if isParam {
2206 ret.WriteString("params")
2207 } else {
2208 ret.WriteString("results")
2209 }
2210 if context != "" {
2211 if isParam {
2212 ret.WriteString(" for ")
2213 } else {
2214 ret.WriteString(" in ")
2215 }
2216 ret.WriteString(context)
2217 ret.WriteString(" block")
2218 }
2219 ret.WriteString("\n\thave (")
2220 writeValueTypes(have, &ret)
2221 ret.WriteString(")\n\twant (")
2222 writeValueTypes(want, &ret)
2223 ret.WriteByte(')')
2224 return errors.New(ret.String())
2225}
2226
2227func writeValueTypes(vts []ValueType, ret *strings.Builder) {
2228 switch len(vts) {
2229 case 0:
2230 case 1:
2231 ret.WriteString(ValueTypeName(vts[0]))
2232 default:
2233 ret.WriteString(ValueTypeName(vts[0]))
2234 for _, vt := range vts[1:] {
2235 ret.WriteString(", ")
2236 ret.WriteString(ValueTypeName(vt))
2237 }
2238 }
2239}
2240
2241func (s *valueTypeStack) String() string {
2242 var typeStrs, limits []string
2243 for _, v := range s.stack {
2244 var str string
2245 if v == valueTypeUnknown {
2246 str = "unknown"
2247 } else {
2248 str = ValueTypeName(v)
2249 }
2250 typeStrs = append(typeStrs, str)
2251 }
2252 for _, d := range s.stackLimits {
2253 limits = append(limits, fmt.Sprintf("%d", d))
2254 }
2255 return fmt.Sprintf("{stack: [%s], limits: [%s]}",
2256 strings.Join(typeStrs, ", "), strings.Join(limits, ","))
2257}
2258
2259type controlBlock struct {
2260 startAt, elseAt, endAt uint64
2261 blockType *FunctionType
2262 blockTypeBytes uint64
2263 // op is zero when the outermost block
2264 op Opcode
2265}
2266
2267// DecodeBlockType decodes the type index from a positive 33-bit signed integer. Negative numbers indicate up to one
2268// WebAssembly 1.0 (20191205) compatible result type. Positive numbers are decoded when `enabledFeatures` include
2269// CoreFeatureMultiValue and include an index in the Module.TypeSection.
2270//
2271// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-blocktype
2272// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
2273func DecodeBlockType(types []FunctionType, r *bytes.Reader, enabledFeatures api.CoreFeatures) (*FunctionType, uint64, error) {
2274 raw, num, err := leb128.DecodeInt33AsInt64(r)
2275 if err != nil {
2276 return nil, 0, fmt.Errorf("decode int33: %w", err)
2277 }
2278
2279 var ret *FunctionType
2280 switch raw {
2281 case -64: // 0x40 in original byte = nil
2282 ret = blockType_v_v
2283 case -1: // 0x7f in original byte = i32
2284 ret = blockType_v_i32
2285 case -2: // 0x7e in original byte = i64
2286 ret = blockType_v_i64
2287 case -3: // 0x7d in original byte = f32
2288 ret = blockType_v_f32
2289 case -4: // 0x7c in original byte = f64
2290 ret = blockType_v_f64
2291 case -5: // 0x7b in original byte = v128
2292 ret = blockType_v_v128
2293 case -16: // 0x70 in original byte = funcref
2294 ret = blockType_v_funcref
2295 case -17: // 0x6f in original byte = externref
2296 ret = blockType_v_externref
2297 default:
2298 if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
2299 return nil, num, fmt.Errorf("block with function type return invalid as %v", err)
2300 }
2301 if raw < 0 || (raw >= int64(len(types))) {
2302 return nil, 0, fmt.Errorf("type index out of range: %d", raw)
2303 }
2304 ret = &types[raw]
2305 }
2306 return ret, num, err
2307}
2308
2309// These block types are defined as globals in order to avoid allocations in DecodeBlockType.
2310var (
2311 blockType_v_v = &FunctionType{}
2312 blockType_v_i32 = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1}
2313 blockType_v_i64 = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1}
2314 blockType_v_f32 = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1}
2315 blockType_v_f64 = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1}
2316 blockType_v_v128 = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2}
2317 blockType_v_funcref = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1}
2318 blockType_v_externref = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1}
2319)
2320
2321// SplitCallStack returns the input stack resliced to the count of params and
2322// results, or errors if it isn't long enough for either.
2323func SplitCallStack(ft *FunctionType, stack []uint64) (params []uint64, results []uint64, err error) {
2324 stackLen := len(stack)
2325 if n := ft.ParamNumInUint64; n > stackLen {
2326 return nil, nil, fmt.Errorf("need %d params, but stack size is %d", n, stackLen)
2327 } else if n > 0 {
2328 params = stack[:n]
2329 }
2330 if n := ft.ResultNumInUint64; n > stackLen {
2331 return nil, nil, fmt.Errorf("need %d results, but stack size is %d", n, stackLen)
2332 } else if n > 0 {
2333 results = stack[:n]
2334 }
2335 return
2336}