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