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