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