github.com/taubyte/vm-wasm-utils@v1.0.2/func_validation.go (about) 1 package wasm 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "strconv" 8 "strings" 9 10 "github.com/taubyte/vm-wasm-utils/buildoptions" 11 "github.com/taubyte/vm-wasm-utils/leb128" 12 "github.com/tetratelabs/wazero/api" 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 namespace, which is prefixed by imports. The value is the TypeSection index. 23 // * globals are the global index namespace, 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(enabledFeatures Features, idx Index, functions []Index, 31 globals []*GlobalType, memory *Memory, tables []*Table, declaredFunctionIndexes map[Index]struct{}) 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.DecodeUint32(bytes.NewReader(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.DecodeUint32(bytes.NewReader(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 Features, 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 buildoptions.IsDebugMode { 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.DecodeUint32(bytes.NewReader(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.DecodeInt32(bytes.NewReader(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.DecodeInt64(bytes.NewReader(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.DecodeUint32(bytes.NewReader(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.DecodeUint32(bytes.NewReader(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.DecodeUint32(bytes.NewReader(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.Get(FeatureReferenceTypes) { 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.DecodeUint32(bytes.NewReader(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.DecodeUint32(bytes.NewReader(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.DecodeUint32(bytes.NewReader(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.Require(FeatureReferenceTypes); 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.Require(FeatureSignExtensionOps); 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.Require(FeatureSignExtensionOps); 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.Require(FeatureReferenceTypes); 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.DecodeUint32(bytes.NewReader(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.Require(FeatureReferenceTypes); err != nil { 843 return fmt.Errorf("%s is invalid as %v", InstructionName(op), err) 844 } 845 pc++ 846 tableIndex, num, err := leb128.DecodeUint32(bytes.NewReader(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 // Miscellaneous instructions come with two bytes which starts with OpcodeMiscPrefix, 872 // and the second byte determines the actual instruction. 873 miscOpcode := body[pc] 874 if miscOpcode >= OpcodeMiscI32TruncSatF32S && miscOpcode <= OpcodeMiscI64TruncSatF64U { 875 if err := enabledFeatures.Require(FeatureNonTrappingFloatToIntConversion); err != nil { 876 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err) 877 } 878 var inType, outType ValueType 879 switch miscOpcode { 880 case OpcodeMiscI32TruncSatF32S, OpcodeMiscI32TruncSatF32U: 881 inType, outType = ValueTypeF32, ValueTypeI32 882 case OpcodeMiscI32TruncSatF64S, OpcodeMiscI32TruncSatF64U: 883 inType, outType = ValueTypeF64, ValueTypeI32 884 case OpcodeMiscI64TruncSatF32S, OpcodeMiscI64TruncSatF32U: 885 inType, outType = ValueTypeF32, ValueTypeI64 886 case OpcodeMiscI64TruncSatF64S, OpcodeMiscI64TruncSatF64U: 887 inType, outType = ValueTypeF64, ValueTypeI64 888 } 889 if err := valueTypeStack.popAndVerifyType(inType); err != nil { 890 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err) 891 } 892 valueTypeStack.push(outType) 893 } else if miscOpcode >= OpcodeMiscMemoryInit && miscOpcode <= OpcodeMiscTableCopy { 894 if err := enabledFeatures.Require(FeatureBulkMemoryOperations); err != nil { 895 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err) 896 } 897 var params []ValueType 898 // Handle opcodes added in bulk-memory-operations/WebAssembly 2.0. 899 switch miscOpcode { 900 case OpcodeMiscDataDrop: 901 if m.DataCountSection == nil { 902 return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode)) 903 } 904 905 // We need to read the index to the data section. 906 pc++ 907 index, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 908 if err != nil { 909 return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err) 910 } 911 if int(index) >= len(m.DataSection) { 912 return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection)) 913 } 914 pc += num - 1 915 case OpcodeMiscMemoryInit, OpcodeMiscMemoryCopy, OpcodeMiscMemoryFill: 916 if memory == nil { 917 return fmt.Errorf("memory must exist for %s", MiscInstructionName(miscOpcode)) 918 } 919 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32} 920 921 if miscOpcode == OpcodeMiscMemoryInit { 922 if m.DataCountSection == nil { 923 return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode)) 924 } 925 926 // We need to read the index to the data section. 927 pc++ 928 index, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 929 if err != nil { 930 return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err) 931 } 932 if int(index) >= len(m.DataSection) { 933 return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection)) 934 } 935 pc += num - 1 936 } 937 938 pc++ 939 val, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 940 if err != nil { 941 return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err) 942 } 943 if val != 0 || num != 1 { 944 return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode)) 945 } 946 if miscOpcode == OpcodeMiscMemoryCopy { 947 pc++ 948 // memory.copy needs two memory index which are reserved as zero. 949 val, num, err := leb128.DecodeUint32(bytes.NewReader(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 } 957 958 case OpcodeMiscTableInit: 959 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32} 960 pc++ 961 elementIndex, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 962 if err != nil { 963 return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err) 964 } 965 if int(elementIndex) >= len(m.ElementSection) { 966 return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection)) 967 } 968 pc += num 969 970 tableIndex, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 971 if err != nil { 972 return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err) 973 } 974 if tableIndex != 0 { 975 if err := enabledFeatures.Require(FeatureReferenceTypes); err != nil { 976 return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err) 977 } 978 } 979 if tableIndex >= uint32(len(tables)) { 980 return fmt.Errorf("table of index %d not found", tableIndex) 981 } 982 983 if m.ElementSection[elementIndex].Type != tables[tableIndex].Type { 984 return fmt.Errorf("type mismatch for table.init: element type %s does not match table type %s", 985 RefTypeName(m.ElementSection[elementIndex].Type), 986 RefTypeName(tables[tableIndex].Type), 987 ) 988 } 989 pc += num - 1 990 case OpcodeMiscElemDrop: 991 pc++ 992 elementIndex, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 993 if err != nil { 994 return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err) 995 } else if int(elementIndex) >= len(m.ElementSection) { 996 return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection)) 997 } 998 pc += num - 1 999 case OpcodeMiscTableCopy: 1000 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32} 1001 pc++ 1002 1003 dstTableIndex, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 1004 if err != nil { 1005 return fmt.Errorf("failed to read destination table index for %s: %v", MiscInstructionName(miscOpcode), err) 1006 } 1007 if dstTableIndex != 0 { 1008 if err := enabledFeatures.Require(FeatureReferenceTypes); err != nil { 1009 return fmt.Errorf("destination table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err) 1010 } 1011 } 1012 if dstTableIndex >= uint32(len(tables)) { 1013 return fmt.Errorf("table of index %d not found", dstTableIndex) 1014 } 1015 pc += num 1016 1017 srcTableIndex, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 1018 if err != nil { 1019 return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err) 1020 } 1021 if srcTableIndex != 0 { 1022 if err := enabledFeatures.Require(FeatureReferenceTypes); err != nil { 1023 return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err) 1024 } 1025 } 1026 if srcTableIndex >= uint32(len(tables)) { 1027 return fmt.Errorf("table of index %d not found", srcTableIndex) 1028 } 1029 1030 if tables[srcTableIndex].Type != tables[dstTableIndex].Type { 1031 return fmt.Errorf("table type mismatch for table.copy: %s (src) != %s (dst)", 1032 RefTypeName(tables[srcTableIndex].Type), RefTypeName(tables[dstTableIndex].Type)) 1033 } 1034 1035 pc += num - 1 1036 } 1037 for _, p := range params { 1038 if err := valueTypeStack.popAndVerifyType(p); err != nil { 1039 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err) 1040 } 1041 } 1042 } else if miscOpcode >= OpcodeMiscTableGrow && miscOpcode <= OpcodeMiscTableFill { 1043 if err := enabledFeatures.Require(FeatureReferenceTypes); err != nil { 1044 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err) 1045 } 1046 1047 pc++ 1048 tableIndex, num, err := leb128.DecodeUint32(bytes.NewReader(body[pc:])) 1049 if err != nil { 1050 return fmt.Errorf("failed to read table index for %s: %v", MiscInstructionName(miscOpcode), err) 1051 } 1052 if tableIndex >= uint32(len(tables)) { 1053 return fmt.Errorf("table of index %d not found", tableIndex) 1054 } 1055 pc += num - 1 1056 1057 var params, results []ValueType 1058 reftype := tables[tableIndex].Type 1059 if miscOpcode == OpcodeMiscTableGrow { 1060 params = []ValueType{ValueTypeI32, reftype} 1061 results = []ValueType{ValueTypeI32} 1062 } else if miscOpcode == OpcodeMiscTableSize { 1063 results = []ValueType{ValueTypeI32} 1064 } else if miscOpcode == OpcodeMiscTableFill { 1065 params = []ValueType{ValueTypeI32, reftype, ValueTypeI32} 1066 } 1067 1068 for _, p := range params { 1069 if err := valueTypeStack.popAndVerifyType(p); err != nil { 1070 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err) 1071 } 1072 } 1073 for _, r := range results { 1074 valueTypeStack.push(r) 1075 } 1076 } 1077 } else if op == OpcodeVecPrefix { 1078 pc++ 1079 // Vector instructions come with two bytes where the first byte is always OpcodeVecPrefix, 1080 // and the second byte determines the actual instruction. 1081 vecOpcode := body[pc] 1082 if err := enabledFeatures.Require(FeatureSIMD); err != nil { 1083 return fmt.Errorf("%s invalid as %v", vectorInstructionName[vecOpcode], err) 1084 } 1085 1086 switch vecOpcode { 1087 case OpcodeVecV128Const: 1088 // Read 128-bit = 16 bytes constants 1089 if int(pc+16) >= len(body) { 1090 return fmt.Errorf("cannot read constant vector value for %s", vectorInstructionName[vecOpcode]) 1091 } 1092 pc += 16 1093 valueTypeStack.push(ValueTypeV128) 1094 case OpcodeVecV128AnyTrue, OpcodeVecI8x16AllTrue, OpcodeVecI16x8AllTrue, OpcodeVecI32x4AllTrue, OpcodeVecI64x2AllTrue, 1095 OpcodeVecI8x16BitMask, OpcodeVecI16x8BitMask, OpcodeVecI32x4BitMask, OpcodeVecI64x2BitMask: 1096 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1097 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1098 } 1099 valueTypeStack.push(ValueTypeI32) 1100 case OpcodeVecV128Load, OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u, 1101 OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat, 1102 OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat, 1103 OpcodeVecV128Load32zero, OpcodeVecV128Load64zero: 1104 if memory == nil && !code.IsHostFunction { 1105 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) 1106 } 1107 pc++ 1108 align, _, read, err := readMemArg(pc, body) 1109 if err != nil { 1110 return err 1111 } 1112 pc += read - 1 1113 var maxAlign uint32 1114 switch vecOpcode { 1115 case OpcodeVecV128Load: 1116 maxAlign = 128 / 8 1117 case OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u, 1118 OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u: 1119 maxAlign = 64 / 8 1120 case OpcodeVecV128Load8Splat: 1121 maxAlign = 1 1122 case OpcodeVecV128Load16Splat: 1123 maxAlign = 16 / 8 1124 case OpcodeVecV128Load32Splat: 1125 maxAlign = 32 / 8 1126 case OpcodeVecV128Load64Splat: 1127 maxAlign = 64 / 8 1128 case OpcodeVecV128Load32zero: 1129 maxAlign = 32 / 8 1130 case OpcodeVecV128Load64zero: 1131 maxAlign = 64 / 8 1132 } 1133 1134 if 1<<align > maxAlign { 1135 return fmt.Errorf("invalid memory alignment %d for %s", align, VectorInstructionName(vecOpcode)) 1136 } 1137 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { 1138 return fmt.Errorf("cannot pop the operand for %s: %v", VectorInstructionName(vecOpcode), err) 1139 } 1140 valueTypeStack.push(ValueTypeV128) 1141 case OpcodeVecV128Store: 1142 if memory == nil && !code.IsHostFunction { 1143 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) 1144 } 1145 pc++ 1146 align, _, read, err := readMemArg(pc, body) 1147 if err != nil { 1148 return err 1149 } 1150 pc += read - 1 1151 if 1<<align > 128/8 { 1152 return fmt.Errorf("invalid memory alignment %d for %s", align, OpcodeVecV128StoreName) 1153 } 1154 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1155 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err) 1156 } 1157 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { 1158 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err) 1159 } 1160 case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane: 1161 if memory == nil && !code.IsHostFunction { 1162 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) 1163 } 1164 attr := vecLoadLanes[vecOpcode] 1165 pc++ 1166 align, _, read, err := readMemArg(pc, body) 1167 if err != nil { 1168 return err 1169 } 1170 if 1<<align > attr.alignMax { 1171 return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode]) 1172 } 1173 pc += read 1174 if pc >= uint64(len(body)) { 1175 return fmt.Errorf("lane for %s not found", OpcodeVecV128Load64LaneName) 1176 } 1177 lane := body[pc] 1178 if lane >= attr.laneCeil { 1179 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) 1180 } 1181 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1182 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1183 } 1184 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { 1185 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1186 } 1187 valueTypeStack.push(ValueTypeV128) 1188 case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane: 1189 if memory == nil && !code.IsHostFunction { 1190 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode)) 1191 } 1192 attr := vecStoreLanes[vecOpcode] 1193 pc++ 1194 align, _, read, err := readMemArg(pc, body) 1195 if err != nil { 1196 return err 1197 } 1198 if 1<<align > attr.alignMax { 1199 return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode]) 1200 } 1201 pc += read 1202 if pc >= uint64(len(body)) { 1203 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode]) 1204 } 1205 lane := body[pc] 1206 if lane >= attr.laneCeil { 1207 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) 1208 } 1209 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1210 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1211 } 1212 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { 1213 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1214 } 1215 case OpcodeVecI8x16ExtractLaneS, 1216 OpcodeVecI8x16ExtractLaneU, 1217 OpcodeVecI16x8ExtractLaneS, 1218 OpcodeVecI16x8ExtractLaneU, 1219 OpcodeVecI32x4ExtractLane, 1220 OpcodeVecI64x2ExtractLane, 1221 OpcodeVecF32x4ExtractLane, 1222 OpcodeVecF64x2ExtractLane: 1223 pc++ 1224 if pc >= uint64(len(body)) { 1225 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode]) 1226 } 1227 attr := vecExtractLanes[vecOpcode] 1228 lane := body[pc] 1229 if lane >= attr.laneCeil { 1230 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) 1231 } 1232 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1233 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1234 } 1235 valueTypeStack.push(attr.resultType) 1236 case OpcodeVecI8x16ReplaceLane, OpcodeVecI16x8ReplaceLane, OpcodeVecI32x4ReplaceLane, 1237 OpcodeVecI64x2ReplaceLane, OpcodeVecF32x4ReplaceLane, OpcodeVecF64x2ReplaceLane: 1238 pc++ 1239 if pc >= uint64(len(body)) { 1240 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode]) 1241 } 1242 attr := vecReplaceLanes[vecOpcode] 1243 lane := body[pc] 1244 if lane >= attr.laneCeil { 1245 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode]) 1246 } 1247 if err := valueTypeStack.popAndVerifyType(attr.paramType); err != nil { 1248 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1249 } 1250 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1251 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1252 } 1253 valueTypeStack.push(ValueTypeV128) 1254 case OpcodeVecI8x16Splat, OpcodeVecI16x8Splat, OpcodeVecI32x4Splat, 1255 OpcodeVecI64x2Splat, OpcodeVecF32x4Splat, OpcodeVecF64x2Splat: 1256 tp := vecSplatValueTypes[vecOpcode] 1257 if err := valueTypeStack.popAndVerifyType(tp); err != nil { 1258 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1259 } 1260 valueTypeStack.push(ValueTypeV128) 1261 case OpcodeVecI8x16Swizzle, OpcodeVecV128And, OpcodeVecV128Or, OpcodeVecV128Xor, OpcodeVecV128AndNot: 1262 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1263 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1264 } 1265 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1266 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1267 } 1268 valueTypeStack.push(ValueTypeV128) 1269 case OpcodeVecV128Bitselect: 1270 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1271 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1272 } 1273 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1274 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1275 } 1276 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1277 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1278 } 1279 valueTypeStack.push(ValueTypeV128) 1280 case OpcodeVecV128Not: 1281 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1282 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1283 } 1284 valueTypeStack.push(ValueTypeV128) 1285 case OpcodeVecV128i8x16Shuffle: 1286 pc++ 1287 if pc+15 >= uint64(len(body)) { 1288 return fmt.Errorf("16 lane indexes for %s not found", vectorInstructionName[vecOpcode]) 1289 } 1290 lanes := body[pc : pc+16] 1291 for i, l := range lanes { 1292 if l >= 32 { 1293 return fmt.Errorf("invalid lane index[%d] %d >= %d for %s", i, l, 32, vectorInstructionName[vecOpcode]) 1294 } 1295 } 1296 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1297 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1298 } 1299 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1300 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1301 } 1302 valueTypeStack.push(ValueTypeV128) 1303 pc += 15 1304 case OpcodeVecI8x16Shl, OpcodeVecI8x16ShrS, OpcodeVecI8x16ShrU, 1305 OpcodeVecI16x8Shl, OpcodeVecI16x8ShrS, OpcodeVecI16x8ShrU, 1306 OpcodeVecI32x4Shl, OpcodeVecI32x4ShrS, OpcodeVecI32x4ShrU, 1307 OpcodeVecI64x2Shl, OpcodeVecI64x2ShrS, OpcodeVecI64x2ShrU: 1308 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { 1309 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1310 } 1311 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1312 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1313 } 1314 valueTypeStack.push(ValueTypeV128) 1315 case OpcodeVecI8x16Eq, OpcodeVecI8x16Ne, OpcodeVecI8x16LtS, OpcodeVecI8x16LtU, OpcodeVecI8x16GtS, 1316 OpcodeVecI8x16GtU, OpcodeVecI8x16LeS, OpcodeVecI8x16LeU, OpcodeVecI8x16GeS, OpcodeVecI8x16GeU, 1317 OpcodeVecI16x8Eq, OpcodeVecI16x8Ne, OpcodeVecI16x8LtS, OpcodeVecI16x8LtU, OpcodeVecI16x8GtS, 1318 OpcodeVecI16x8GtU, OpcodeVecI16x8LeS, OpcodeVecI16x8LeU, OpcodeVecI16x8GeS, OpcodeVecI16x8GeU, 1319 OpcodeVecI32x4Eq, OpcodeVecI32x4Ne, OpcodeVecI32x4LtS, OpcodeVecI32x4LtU, OpcodeVecI32x4GtS, 1320 OpcodeVecI32x4GtU, OpcodeVecI32x4LeS, OpcodeVecI32x4LeU, OpcodeVecI32x4GeS, OpcodeVecI32x4GeU, 1321 OpcodeVecI64x2Eq, OpcodeVecI64x2Ne, OpcodeVecI64x2LtS, OpcodeVecI64x2GtS, OpcodeVecI64x2LeS, 1322 OpcodeVecI64x2GeS, OpcodeVecF32x4Eq, OpcodeVecF32x4Ne, OpcodeVecF32x4Lt, OpcodeVecF32x4Gt, 1323 OpcodeVecF32x4Le, OpcodeVecF32x4Ge, OpcodeVecF64x2Eq, OpcodeVecF64x2Ne, OpcodeVecF64x2Lt, 1324 OpcodeVecF64x2Gt, OpcodeVecF64x2Le, OpcodeVecF64x2Ge, 1325 OpcodeVecI32x4DotI16x8S, 1326 OpcodeVecI8x16NarrowI16x8S, OpcodeVecI8x16NarrowI16x8U, OpcodeVecI16x8NarrowI32x4S, OpcodeVecI16x8NarrowI32x4U: 1327 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1328 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1329 } 1330 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1331 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1332 } 1333 valueTypeStack.push(ValueTypeV128) 1334 case OpcodeVecI8x16Neg, OpcodeVecI16x8Neg, OpcodeVecI32x4Neg, OpcodeVecI64x2Neg, OpcodeVecF32x4Neg, OpcodeVecF64x2Neg, 1335 OpcodeVecF32x4Sqrt, OpcodeVecF64x2Sqrt, 1336 OpcodeVecI8x16Abs, OpcodeVecI8x16Popcnt, OpcodeVecI16x8Abs, OpcodeVecI32x4Abs, OpcodeVecI64x2Abs, 1337 OpcodeVecF32x4Abs, OpcodeVecF64x2Abs, 1338 OpcodeVecF32x4Ceil, OpcodeVecF32x4Floor, OpcodeVecF32x4Trunc, OpcodeVecF32x4Nearest, 1339 OpcodeVecF64x2Ceil, OpcodeVecF64x2Floor, OpcodeVecF64x2Trunc, OpcodeVecF64x2Nearest, 1340 OpcodeVecI16x8ExtendLowI8x16S, OpcodeVecI16x8ExtendHighI8x16S, OpcodeVecI16x8ExtendLowI8x16U, OpcodeVecI16x8ExtendHighI8x16U, 1341 OpcodeVecI32x4ExtendLowI16x8S, OpcodeVecI32x4ExtendHighI16x8S, OpcodeVecI32x4ExtendLowI16x8U, OpcodeVecI32x4ExtendHighI16x8U, 1342 OpcodeVecI64x2ExtendLowI32x4S, OpcodeVecI64x2ExtendHighI32x4S, OpcodeVecI64x2ExtendLowI32x4U, OpcodeVecI64x2ExtendHighI32x4U, 1343 OpcodeVecI16x8ExtaddPairwiseI8x16S, OpcodeVecI16x8ExtaddPairwiseI8x16U, 1344 OpcodeVecI32x4ExtaddPairwiseI16x8S, OpcodeVecI32x4ExtaddPairwiseI16x8U, 1345 OpcodeVecF64x2PromoteLowF32x4Zero, OpcodeVecF32x4DemoteF64x2Zero, 1346 OpcodeVecF32x4ConvertI32x4S, OpcodeVecF32x4ConvertI32x4U, 1347 OpcodeVecF64x2ConvertLowI32x4S, OpcodeVecF64x2ConvertLowI32x4U, 1348 OpcodeVecI32x4TruncSatF32x4S, OpcodeVecI32x4TruncSatF32x4U, OpcodeVecI32x4TruncSatF64x2SZero, OpcodeVecI32x4TruncSatF64x2UZero: 1349 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1350 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1351 } 1352 valueTypeStack.push(ValueTypeV128) 1353 1354 case OpcodeVecI8x16Add, OpcodeVecI8x16AddSatS, OpcodeVecI8x16AddSatU, OpcodeVecI8x16Sub, OpcodeVecI8x16SubSatS, OpcodeVecI8x16SubSatU, 1355 OpcodeVecI16x8Add, OpcodeVecI16x8AddSatS, OpcodeVecI16x8AddSatU, OpcodeVecI16x8Sub, OpcodeVecI16x8SubSatS, OpcodeVecI16x8SubSatU, OpcodeVecI16x8Mul, 1356 OpcodeVecI32x4Add, OpcodeVecI32x4Sub, OpcodeVecI32x4Mul, 1357 OpcodeVecI64x2Add, OpcodeVecI64x2Sub, OpcodeVecI64x2Mul, 1358 OpcodeVecF32x4Add, OpcodeVecF32x4Sub, OpcodeVecF32x4Mul, OpcodeVecF32x4Div, 1359 OpcodeVecF64x2Add, OpcodeVecF64x2Sub, OpcodeVecF64x2Mul, OpcodeVecF64x2Div, 1360 OpcodeVecI8x16MinS, OpcodeVecI8x16MinU, OpcodeVecI8x16MaxS, OpcodeVecI8x16MaxU, 1361 OpcodeVecI8x16AvgrU, 1362 OpcodeVecI16x8MinS, OpcodeVecI16x8MinU, OpcodeVecI16x8MaxS, OpcodeVecI16x8MaxU, 1363 OpcodeVecI16x8AvgrU, 1364 OpcodeVecI32x4MinS, OpcodeVecI32x4MinU, OpcodeVecI32x4MaxS, OpcodeVecI32x4MaxU, 1365 OpcodeVecF32x4Min, OpcodeVecF32x4Max, OpcodeVecF64x2Min, OpcodeVecF64x2Max, 1366 OpcodeVecF32x4Pmin, OpcodeVecF32x4Pmax, OpcodeVecF64x2Pmin, OpcodeVecF64x2Pmax, 1367 OpcodeVecI16x8Q15mulrSatS, 1368 OpcodeVecI16x8ExtMulLowI8x16S, OpcodeVecI16x8ExtMulHighI8x16S, OpcodeVecI16x8ExtMulLowI8x16U, OpcodeVecI16x8ExtMulHighI8x16U, 1369 OpcodeVecI32x4ExtMulLowI16x8S, OpcodeVecI32x4ExtMulHighI16x8S, OpcodeVecI32x4ExtMulLowI16x8U, OpcodeVecI32x4ExtMulHighI16x8U, 1370 OpcodeVecI64x2ExtMulLowI32x4S, OpcodeVecI64x2ExtMulHighI32x4S, OpcodeVecI64x2ExtMulLowI32x4U, OpcodeVecI64x2ExtMulHighI32x4U: 1371 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1372 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1373 } 1374 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil { 1375 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err) 1376 } 1377 valueTypeStack.push(ValueTypeV128) 1378 default: 1379 return fmt.Errorf("TODO: SIMD instruction %s will be implemented in #506", vectorInstructionName[vecOpcode]) 1380 } 1381 } else if op == OpcodeBlock { 1382 bt, num, err := DecodeBlockType(types, bytes.NewReader(body[pc+1:]), enabledFeatures) 1383 if err != nil { 1384 return fmt.Errorf("read block: %w", err) 1385 } 1386 controlBlockStack = append(controlBlockStack, &controlBlock{ 1387 startAt: pc, 1388 blockType: bt, 1389 blockTypeBytes: num, 1390 }) 1391 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil { 1392 return err 1393 } 1394 // Plus we have to push any block params again. 1395 for _, p := range bt.Params { 1396 valueTypeStack.push(p) 1397 } 1398 valueTypeStack.pushStackLimit(len(bt.Params)) 1399 pc += num 1400 } else if op == OpcodeLoop { 1401 bt, num, err := DecodeBlockType(types, bytes.NewReader(body[pc+1:]), enabledFeatures) 1402 if err != nil { 1403 return fmt.Errorf("read block: %w", err) 1404 } 1405 controlBlockStack = append(controlBlockStack, &controlBlock{ 1406 startAt: pc, 1407 blockType: bt, 1408 blockTypeBytes: num, 1409 op: op, 1410 }) 1411 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil { 1412 return err 1413 } 1414 // Plus we have to push any block params again. 1415 for _, p := range bt.Params { 1416 valueTypeStack.push(p) 1417 } 1418 valueTypeStack.pushStackLimit(len(bt.Params)) 1419 pc += num 1420 } else if op == OpcodeIf { 1421 bt, num, err := DecodeBlockType(types, bytes.NewReader(body[pc+1:]), enabledFeatures) 1422 if err != nil { 1423 return fmt.Errorf("read block: %w", err) 1424 } 1425 controlBlockStack = append(controlBlockStack, &controlBlock{ 1426 startAt: pc, 1427 blockType: bt, 1428 blockTypeBytes: num, 1429 op: op, 1430 }) 1431 if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { 1432 return fmt.Errorf("cannot pop the operand for 'if': %v", err) 1433 } 1434 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil { 1435 return err 1436 } 1437 // Plus we have to push any block params again. 1438 for _, p := range bt.Params { 1439 valueTypeStack.push(p) 1440 } 1441 valueTypeStack.pushStackLimit(len(bt.Params)) 1442 pc += num 1443 } else if op == OpcodeElse { 1444 bl := controlBlockStack[len(controlBlockStack)-1] 1445 bl.elseAt = pc 1446 // Check the type soundness of the instructions *before* entering this else Op. 1447 if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil { 1448 return err 1449 } 1450 // Before entering instructions inside else, we pop all the values pushed by then block. 1451 valueTypeStack.resetAtStackLimit() 1452 // Plus we have to push any block params again. 1453 for _, p := range bl.blockType.Params { 1454 valueTypeStack.push(p) 1455 } 1456 } else if op == OpcodeEnd { 1457 bl := controlBlockStack[len(controlBlockStack)-1] 1458 bl.endAt = pc 1459 controlBlockStack = controlBlockStack[:len(controlBlockStack)-1] 1460 1461 // OpcodeEnd can end a block or the function itself. Check to see what it is: 1462 1463 ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt 1464 if ifMissingElse { 1465 // If this is the end of block without else, the number of block's results and params must be same. 1466 // Otherwise, the value stack would result in the inconsistent state at runtime. 1467 if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) { 1468 return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results) 1469 } 1470 // -1 skips else, to handle if block without else properly. 1471 bl.elseAt = bl.endAt - 1 1472 } 1473 1474 // Determine the block context 1475 ctx := "" // the outer-most block: the function return 1476 if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 { 1477 ctx = OpcodeElseName 1478 } else if bl.op != 0 { 1479 ctx = InstructionName(bl.op) 1480 } 1481 1482 // Check return types match 1483 if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil { 1484 return err 1485 } 1486 1487 // Put the result types at the end after resetting at the stack limit 1488 // since we might have Any type between the limit and the current top. 1489 valueTypeStack.resetAtStackLimit() 1490 for _, exp := range bl.blockType.Results { 1491 valueTypeStack.push(exp) 1492 } 1493 // We exit if/loop/block, so reset the constraints on the stack manipulation 1494 // on values previously pushed by outer blocks. 1495 valueTypeStack.popStackLimit() 1496 } else if op == OpcodeReturn { 1497 // Same formatting as OpcodeEnd on the outer-most block 1498 if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil { 1499 return err 1500 } 1501 // return instruction is stack-polymorphic. 1502 valueTypeStack.unreachable() 1503 } else if op == OpcodeDrop { 1504 _, err := valueTypeStack.pop() 1505 if err != nil { 1506 return fmt.Errorf("invalid drop: %v", err) 1507 } 1508 } else if op == OpcodeSelect || op == OpcodeTypedSelect { 1509 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil { 1510 return fmt.Errorf("type mismatch on 3rd select operand: %v", err) 1511 } 1512 v1, err := valueTypeStack.pop() 1513 if err != nil { 1514 return fmt.Errorf("invalid select: %v", err) 1515 } 1516 v2, err := valueTypeStack.pop() 1517 if err != nil { 1518 return fmt.Errorf("invalid select: %v", err) 1519 } 1520 1521 if op == OpcodeTypedSelect { 1522 if err := enabledFeatures.Require(FeatureReferenceTypes); err != nil { 1523 return fmt.Errorf("%s is invalid as %w", InstructionName(op), err) 1524 } 1525 pc++ 1526 if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 { 1527 return fmt.Errorf("too many type immediates for %s", InstructionName(op)) 1528 } 1529 pc++ 1530 tp := body[pc] 1531 if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 && 1532 tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 { 1533 return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName) 1534 } 1535 } else if isReferenceValueType(v1) || isReferenceValueType(v2) { 1536 return fmt.Errorf("reference types cannot be used for non typed select instruction") 1537 } 1538 1539 if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown { 1540 return fmt.Errorf("type mismatch on 1st and 2nd select operands") 1541 } 1542 if v1 == valueTypeUnknown { 1543 valueTypeStack.push(v2) 1544 } else { 1545 valueTypeStack.push(v1) 1546 } 1547 } else if op == OpcodeUnreachable { 1548 // unreachable instruction is stack-polymorphic. 1549 valueTypeStack.unreachable() 1550 } else if op == OpcodeNop { 1551 } else { 1552 return fmt.Errorf("invalid instruction 0x%x", op) 1553 } 1554 } 1555 1556 if len(controlBlockStack) > 0 { 1557 return fmt.Errorf("ill-nested block exists") 1558 } 1559 if valueTypeStack.maximumStackPointer > maxStackValues { 1560 return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues) 1561 } 1562 return nil 1563 } 1564 1565 var vecExtractLanes = [...]struct { 1566 laneCeil byte 1567 resultType ValueType 1568 }{ 1569 OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32}, 1570 OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32}, 1571 OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32}, 1572 OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32}, 1573 OpcodeVecI32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeI32}, 1574 OpcodeVecI64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeI64}, 1575 OpcodeVecF32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeF32}, 1576 OpcodeVecF64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeF64}, 1577 } 1578 1579 var vecReplaceLanes = [...]struct { 1580 laneCeil byte 1581 paramType ValueType 1582 }{ 1583 OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32}, 1584 OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32}, 1585 OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32}, 1586 OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64}, 1587 OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32}, 1588 OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64}, 1589 } 1590 1591 var vecStoreLanes = [...]struct { 1592 alignMax uint32 1593 laneCeil byte 1594 }{ 1595 OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64}, 1596 OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32}, 1597 OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16}, 1598 OpcodeVecV128Store8Lane: {alignMax: 1, laneCeil: 128 / 8}, 1599 } 1600 1601 var vecLoadLanes = [...]struct { 1602 alignMax uint32 1603 laneCeil byte 1604 }{ 1605 OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64}, 1606 OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32}, 1607 OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16}, 1608 OpcodeVecV128Load8Lane: {alignMax: 1, laneCeil: 128 / 8}, 1609 } 1610 1611 var vecSplatValueTypes = [...]ValueType{ 1612 OpcodeVecI8x16Splat: ValueTypeI32, 1613 OpcodeVecI16x8Splat: ValueTypeI32, 1614 OpcodeVecI32x4Splat: ValueTypeI32, 1615 OpcodeVecI64x2Splat: ValueTypeI64, 1616 OpcodeVecF32x4Splat: ValueTypeF32, 1617 OpcodeVecF64x2Splat: ValueTypeF64, 1618 } 1619 1620 type valueTypeStack struct { 1621 stack []ValueType 1622 stackLimits []int 1623 maximumStackPointer int 1624 } 1625 1626 const ( 1627 // Only used in the analyzeFunction below. 1628 valueTypeUnknown = ValueType(0xFF) 1629 ) 1630 1631 func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) { 1632 if len(s.stackLimits) > 0 { 1633 limit = s.stackLimits[len(s.stackLimits)-1] 1634 } 1635 stackLen := len(s.stack) 1636 if stackLen <= limit { 1637 return 1638 } else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown { 1639 vt = valueTypeUnknown 1640 ok = true 1641 return 1642 } else { 1643 vt = s.stack[stackLen-1] 1644 s.stack = s.stack[:stackLen-1] 1645 ok = true 1646 return 1647 } 1648 } 1649 1650 func (s *valueTypeStack) pop() (ValueType, error) { 1651 if vt, limit, ok := s.tryPop(); ok { 1652 return vt, nil 1653 } else { 1654 return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit) 1655 } 1656 } 1657 1658 // popAndVerifyType returns an error if the stack value is unexpected. 1659 func (s *valueTypeStack) popAndVerifyType(expected ValueType) error { 1660 have, _, ok := s.tryPop() 1661 if !ok { 1662 return fmt.Errorf("%s missing", ValueTypeName(expected)) 1663 } 1664 if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown { 1665 return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have)) 1666 } 1667 return nil 1668 } 1669 1670 func (s *valueTypeStack) push(v ValueType) { 1671 s.stack = append(s.stack, v) 1672 if sp := len(s.stack); sp > s.maximumStackPointer { 1673 s.maximumStackPointer = sp 1674 } 1675 } 1676 1677 func (s *valueTypeStack) unreachable() { 1678 s.resetAtStackLimit() 1679 s.stack = append(s.stack, valueTypeUnknown) 1680 } 1681 1682 func (s *valueTypeStack) resetAtStackLimit() { 1683 if len(s.stackLimits) != 0 { 1684 s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]] 1685 } else { 1686 s.stack = []ValueType{} 1687 } 1688 } 1689 1690 func (s *valueTypeStack) popStackLimit() { 1691 if len(s.stackLimits) != 0 { 1692 s.stackLimits = s.stackLimits[:len(s.stackLimits)-1] 1693 } 1694 } 1695 1696 // pushStackLimit pushes the control frame's bottom of the stack. 1697 func (s *valueTypeStack) pushStackLimit(params int) { 1698 limit := len(s.stack) - params 1699 s.stackLimits = append(s.stackLimits, limit) 1700 } 1701 1702 func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error { 1703 return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit) 1704 } 1705 1706 func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error { 1707 return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit) 1708 } 1709 1710 func (s *valueTypeStack) requireStackValues( 1711 isParam bool, 1712 context string, 1713 want []ValueType, 1714 checkAboveLimit bool, 1715 ) error { 1716 limit := 0 1717 if len(s.stackLimits) > 0 { 1718 limit = s.stackLimits[len(s.stackLimits)-1] 1719 } 1720 // Iterate backwards as we are comparing the desired slice against stack value types. 1721 countWanted := len(want) 1722 1723 // First, check if there are enough values on the stack. 1724 have := make([]ValueType, 0, countWanted) 1725 for i := countWanted - 1; i >= 0; i-- { 1726 popped, _, ok := s.tryPop() 1727 if !ok { 1728 if len(have) > len(want) { 1729 return typeCountError(isParam, context, have, want) 1730 } 1731 return typeCountError(isParam, context, have, want) 1732 } 1733 have = append(have, popped) 1734 } 1735 1736 // Now, check if there are too many values. 1737 if checkAboveLimit { 1738 if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) { 1739 return typeCountError(isParam, context, append(s.stack, want...), want) 1740 } 1741 } 1742 1743 // Finally, check the types of the values: 1744 for i, v := range have { 1745 nextWant := want[countWanted-i-1] // have is in reverse order (stack) 1746 if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown { 1747 return typeMismatchError(isParam, context, v, nextWant, i) 1748 } 1749 } 1750 return nil 1751 } 1752 1753 // typeMismatchError returns an error similar to go compiler's error on type mismatch. 1754 func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error { 1755 var ret strings.Builder 1756 ret.WriteString("cannot use ") 1757 ret.WriteString(ValueTypeName(have)) 1758 if context != "" { 1759 ret.WriteString(" in ") 1760 ret.WriteString(context) 1761 ret.WriteString(" block") 1762 } 1763 if isParam { 1764 ret.WriteString(" as param") 1765 } else { 1766 ret.WriteString(" as result") 1767 } 1768 ret.WriteString("[") 1769 ret.WriteString(strconv.Itoa(i)) 1770 ret.WriteString("] type ") 1771 ret.WriteString(ValueTypeName(want)) 1772 return errors.New(ret.String()) 1773 } 1774 1775 // typeCountError returns an error similar to go compiler's error on type count mismatch. 1776 func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error { 1777 var ret strings.Builder 1778 if len(have) > len(want) { 1779 ret.WriteString("too many ") 1780 } else { 1781 ret.WriteString("not enough ") 1782 } 1783 if isParam { 1784 ret.WriteString("params") 1785 } else { 1786 ret.WriteString("results") 1787 } 1788 if context != "" { 1789 if isParam { 1790 ret.WriteString(" for ") 1791 } else { 1792 ret.WriteString(" in ") 1793 } 1794 ret.WriteString(context) 1795 ret.WriteString(" block") 1796 } 1797 ret.WriteString("\n\thave (") 1798 writeValueTypes(have, &ret) 1799 ret.WriteString(")\n\twant (") 1800 writeValueTypes(want, &ret) 1801 ret.WriteByte(')') 1802 return errors.New(ret.String()) 1803 } 1804 1805 func writeValueTypes(vts []ValueType, ret *strings.Builder) { 1806 switch len(vts) { 1807 case 0: 1808 case 1: 1809 ret.WriteString(ValueTypeName(vts[0])) 1810 default: 1811 ret.WriteString(ValueTypeName(vts[0])) 1812 for _, vt := range vts[1:] { 1813 ret.WriteString(", ") 1814 ret.WriteString(ValueTypeName(vt)) 1815 } 1816 } 1817 } 1818 1819 func (s *valueTypeStack) String() string { 1820 var typeStrs, limits []string 1821 for _, v := range s.stack { 1822 var str string 1823 if v == valueTypeUnknown { 1824 str = "unknown" 1825 } else { 1826 str = ValueTypeName(v) 1827 } 1828 typeStrs = append(typeStrs, str) 1829 } 1830 for _, d := range s.stackLimits { 1831 limits = append(limits, fmt.Sprintf("%d", d)) 1832 } 1833 return fmt.Sprintf("{stack: [%s], limits: [%s]}", 1834 strings.Join(typeStrs, ", "), strings.Join(limits, ",")) 1835 } 1836 1837 type controlBlock struct { 1838 startAt, elseAt, endAt uint64 1839 blockType *FunctionType 1840 blockTypeBytes uint64 1841 // op is zero when the outermost block 1842 op Opcode 1843 } 1844 1845 // DecodeBlockType decodes the type index from a positive 33-bit signed integer. Negative numbers indicate up to one 1846 // WebAssembly 1.0 (20191205) compatible result type. Positive numbers are decoded when `enabledFeatures` include 1847 // FeatureMultiValue and include an index in the Module.TypeSection. 1848 // 1849 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-blocktype 1850 // See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md 1851 func DecodeBlockType(types []*FunctionType, r *bytes.Reader, enabledFeatures Features) (*FunctionType, uint64, error) { 1852 raw, num, err := leb128.DecodeInt33AsInt64(r) 1853 if err != nil { 1854 return nil, 0, fmt.Errorf("decode int33: %w", err) 1855 } 1856 1857 var ret *FunctionType 1858 switch raw { 1859 case -64: // 0x40 in original byte = nil 1860 ret = &FunctionType{} 1861 case -1: // 0x7f in original byte = i32 1862 ret = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1} 1863 case -2: // 0x7e in original byte = i64 1864 ret = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1} 1865 case -3: // 0x7d in original byte = f32 1866 ret = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1} 1867 case -4: // 0x7c in original byte = f64 1868 ret = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1} 1869 case -5: // 0x7b in original byte = v128 1870 ret = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2} 1871 case -16: // 0x70 in original byte = funcref 1872 ret = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1} 1873 case -17: // 0x6f in original byte = externref 1874 ret = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1} 1875 default: 1876 if err = enabledFeatures.Require(FeatureMultiValue); err != nil { 1877 return nil, num, fmt.Errorf("block with function type return invalid as %v", err) 1878 } 1879 if raw < 0 || (raw >= int64(len(types))) { 1880 return nil, 0, fmt.Errorf("type index out of range: %d", raw) 1881 } 1882 ret = types[raw] 1883 } 1884 return ret, num, err 1885 }