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