1 /** 2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_VERIFICATION_ABSINT_ABS_INT_INL_H 17 #define PANDA_VERIFICATION_ABSINT_ABS_INT_INL_H 18 19 #include "abs_int_inl_compat_checks.h" 20 #include "file_items.h" 21 #include "include/mem/panda_containers.h" 22 #include "include/method.h" 23 #include "include/runtime.h" 24 #include "libpandafile/type_helper.h" 25 #include "macros.h" 26 #include "runtime/include/class.h" 27 #include "runtime/include/thread_scopes.h" 28 #include "type/type_system.h" 29 #include "utils/logger.h" 30 #include "util/str.h" 31 #include "verification/config/debug_breakpoint/breakpoint.h" 32 #include "verification_context.h" 33 #include "verification/type/type_system.h" 34 #include "verification_status.h" 35 #include "verifier_messages.h" 36 37 // CC-OFFNXT(G.PRE.06) solid logic 38 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 39 #define LOG_INST() \ 40 do { \ 41 if (!GetInst().IsValid()) { \ 42 SHOW_MSG(InvalidInstruction) \ 43 LOG_VERIFIER_INVALID_INSTRUCTION(); \ 44 END_SHOW_MSG(); \ 45 SET_STATUS_FOR_MSG(InvalidInstruction, WARNING); \ 46 return false; /* CC-OFF(G.PRE.05) code generation */ \ 47 } \ 48 if (job_->Options().ShowContext()) { \ 49 DumpRegs(ExecCtx().CurrentRegContext()); \ 50 } \ 51 SHOW_MSG(DebugAbsIntLogInstruction) \ 52 LOG_VERIFIER_DEBUG_ABS_INT_LOG_INSTRUCTION(GetInst()); \ 53 END_SHOW_MSG(); \ 54 } while (0) 55 56 #ifndef NDEBUG 57 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 58 #define DBGBRK() \ 59 if (debug_) { \ 60 DBG_MANAGED_BRK(debugCtx, job_->JobMethod()->GetUniqId(), inst_.GetOffset()); \ 61 } 62 #else 63 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 64 #define DBGBRK() 65 #endif 66 67 // CC-OFFNXT(G.PRE.02) namespace member 68 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 69 #define SHOW_MSG(Message) if (!job_->Options().IsHidden(VerifierMessage::Message)) { 70 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 71 #define END_SHOW_MSG() } 72 73 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 74 #define SET_STATUS_FOR_MSG(Message, AtLeast) \ 75 do { \ 76 SetStatusAtLeast(VerificationStatus::AtLeast); /* CC-OFF(G.PRE.02) namespace member */ \ 77 /* CC-OFFNXT(G.PRE.02) namespace member */ \ 78 SetStatusAtLeast(MsgClassToStatus(job_->Options().MsgClassFor(VerifierMessage::Message))); \ 79 } while (0) 80 81 /* 82 NOTE(vdyadov): add AddrMap to verification context where put marks on all checked bytes. 83 after absint process ends, check this AddrMap for holes. 84 holes are either dead byte-code or issues with absint cflow handling. 85 */ 86 87 // NOTE(vdyadov): refactor this file, all utility functions put in separate/other files 88 89 /* 90 NOTE(vdyadov): IMPORTANT!!! (Done) 91 Current definition of context incompatibility is NOT CORRECT one! 92 There are situations when verifier will rule out fully correct programs. 93 For instance: 94 .... 95 movi v0,0 96 ldai 0 97 jmp label1 98 .... 99 lda.str "" 100 sta v0 101 ldai 0 102 jmp label1 103 ..... 104 label1: 105 return 106 107 Here we have context incompatibility on label1, but it does not harm, because conflicting reg is 108 not used anymore. 109 110 Solutions: 111 1(current). Conflicts are reported as warnings, conflicting regs are removed fro resulting context. 112 So, on attempt of usage of conflicting reg, absint will fail with message of undefined reg. 113 May be mark them as conflicting? (done) 114 2. On each label/checkpoint compute set of registers that will be used in next conputations and process 115 conflicting contexts modulo used registers set. It is complex solution, but very preciese. 116 */ 117 118 // NOTE(vdyadov): regain laziness, strict evaluation is very expensive! 119 120 namespace ark::verifier { 121 122 class AbsIntInstructionHandler { 123 public: 124 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 125 static constexpr int ACC = -1; 126 static constexpr int INVALID_REG = -2; // NOTE(vdyadov): may be use Index<..> here? 127 128 using TypeId = panda_file::Type::TypeId; 129 using Builtin = Type::Builtin; 130 131 Type const top_ {Builtin::TOP}; 132 Type const bot_ {Builtin::BOT}; 133 Type const u1_ {Builtin::U1}; 134 Type const i8_ {Builtin::I8}; 135 Type const u8_ {Builtin::U8}; 136 Type const i16_ {Builtin::I16}; 137 Type const u16_ {Builtin::U16}; 138 Type const i32_ {Builtin::I32}; 139 Type const u32_ {Builtin::U32}; 140 Type const i64_ {Builtin::I64}; 141 Type const u64_ {Builtin::U64}; 142 Type const f32_ {Builtin::F32}; 143 Type const f64_ {Builtin::F64}; 144 Type const integral32_ {Builtin::INTEGRAL32}; 145 Type const integral64_ {Builtin::INTEGRAL64}; 146 Type const float32_ {Builtin::FLOAT32}; 147 Type const float64_ {Builtin::FLOAT64}; 148 Type const bits32_ {Builtin::BITS32}; 149 Type const bits64_ {Builtin::BITS64}; 150 Type const primitive_ {Builtin::PRIMITIVE}; 151 Type const refType_ {Builtin::REFERENCE}; 152 Type const nullRefType_ {Builtin::NULL_REFERENCE}; 153 Type const objectType_ {Builtin::OBJECT}; 154 Type const arrayType_ {Builtin::ARRAY}; 155 156 Job const *job_; 157 debug::DebugContext const *debugCtx; 158 Config const *config; 159 160 // NOLINTEND(misc-non-private-member-variables-in-classes) 161 AbsIntInstructionHandler(VerificationContext & verifCtx,const uint8_t * pc,EntryPointType codeType)162 AbsIntInstructionHandler(VerificationContext &verifCtx, const uint8_t *pc, EntryPointType codeType) 163 : job_ {verifCtx.GetJob()}, 164 debugCtx {&job_->GetService()->debugCtx}, 165 config {GetServiceConfig(job_->GetService())}, 166 inst_(pc, verifCtx.CflowInfo().GetAddrStart(), verifCtx.CflowInfo().GetAddrEnd()), 167 context_ {verifCtx}, 168 codeType_ {codeType} 169 { 170 #ifndef NDEBUG 171 if (config->opts.mode == VerificationMode::DEBUG) { 172 const auto &method = job_->JobMethod(); 173 debug_ = debug::ManagedBreakpointPresent(debugCtx, method->GetUniqId()); 174 if (debug_) { 175 LOG(DEBUG, VERIFIER) << "Debug mode for method " << method->GetFullName() << " is on"; 176 } 177 } 178 #endif 179 } 180 181 ~AbsIntInstructionHandler() = default; 182 NO_MOVE_SEMANTIC(AbsIntInstructionHandler); 183 NO_COPY_SEMANTIC(AbsIntInstructionHandler); 184 GetStatus()185 VerificationStatus GetStatus() 186 { 187 return status_; 188 } 189 GetPrimaryOpcode()190 uint8_t GetPrimaryOpcode() 191 { 192 return inst_.GetPrimaryOpcode(); 193 } 194 GetSecondaryOpcode()195 uint8_t GetSecondaryOpcode() 196 { 197 return inst_.GetSecondaryOpcode(); 198 } 199 IsPrimaryOpcodeValid()200 bool IsPrimaryOpcodeValid() const 201 { 202 return inst_.IsPrimaryOpcodeValid(); 203 } 204 205 bool IsRegDefined(int reg); 206 ToString(Type tp)207 PandaString ToString(Type tp) const 208 { 209 return tp.ToString(GetTypeSystem()); 210 } 211 ToString(PandaVector<Type> const & types)212 PandaString ToString(PandaVector<Type> const &types) const 213 { 214 PandaString result {"[ "}; 215 bool comma = false; 216 for (const auto &type : types) { 217 if (comma) { 218 result += ", "; 219 } 220 result += ToString(type); 221 comma = true; 222 } 223 result += " ]"; 224 return result; 225 } 226 ToString(AbstractTypedValue const * atv)227 PandaString ToString(AbstractTypedValue const *atv) const 228 { 229 return atv->ToString(GetTypeSystem()); 230 } 231 StringDataToString(panda_file::File::StringData sd)232 static PandaString StringDataToString(panda_file::File::StringData sd) 233 { 234 PandaString res {reinterpret_cast<char *>(const_cast<uint8_t *>(sd.data))}; 235 return res; 236 } 237 CheckType(Type type,Type tgtType)238 bool CheckType(Type type, Type tgtType) 239 { 240 return IsSubtype(type, tgtType, GetTypeSystem()); 241 } 242 243 bool CheckRegType(int reg, Type tgtType); 244 245 const AbstractTypedValue &GetReg(int regIdx); 246 247 Type GetRegType(int regIdx); 248 249 void SetReg(int regIdx, const AbstractTypedValue &val); 250 void SetReg(int regIdx, Type type); 251 252 void SetRegAndOthersOfSameOrigin(int regIdx, const AbstractTypedValue &val); 253 void SetRegAndOthersOfSameOrigin(int regIdx, Type type); 254 255 const AbstractTypedValue &GetAcc(); 256 257 Type GetAccType(); 258 259 void SetAcc(const AbstractTypedValue &val); 260 void SetAcc(Type type); 261 262 void SetAccAndOthersOfSameOrigin(const AbstractTypedValue &val); 263 void SetAccAndOthersOfSameOrigin(Type type); 264 265 AbstractTypedValue MkVal(Type t); 266 GetTypeSystem()267 TypeSystem *GetTypeSystem() const 268 { 269 return context_.GetTypeSystem(); 270 } 271 272 Type TypeOfClass(Class const *klass); 273 274 Type ReturnType(); 275 276 ExecContext &ExecCtx(); 277 278 void DumpRegs(const RegContext &ctx); 279 280 bool CheckCtxCompatibility(const RegContext &src, const RegContext &dst); 281 282 void Sync(); 283 AssignRegToReg(int dst,int src)284 void AssignRegToReg(int dst, int src) 285 { 286 auto atv = GetReg(src); 287 if (!atv.GetOrigin().IsValid()) { 288 // generate new origin and set all values to be originated at it 289 AbstractTypedValue newAtv {atv, inst_}; 290 SetReg(src, newAtv); 291 SetReg(dst, newAtv); 292 } else { 293 SetReg(dst, atv); 294 } 295 } 296 AssignAccToReg(int src)297 void AssignAccToReg(int src) 298 { 299 AssignRegToReg(ACC, src); 300 } 301 AssignRegToAcc(int dst)302 void AssignRegToAcc(int dst) 303 { 304 AssignRegToReg(dst, ACC); 305 } 306 307 // Names meanings: vs - v_source, vd - v_destination 308 template <BytecodeInstructionSafe::Format FORMAT> HandleMov()309 bool HandleMov() 310 { 311 LOG_INST(); 312 DBGBRK(); 313 uint16_t vd = inst_.GetVReg<FORMAT, 0x00>(); 314 uint16_t vs = inst_.GetVReg<FORMAT, 0x01>(); 315 Sync(); 316 317 if (!CheckRegType(vs, bits32_)) { 318 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 319 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 320 return false; 321 } 322 AssignRegToReg(vd, vs); 323 MoveToNextInst<FORMAT>(); 324 return true; 325 } 326 327 template <BytecodeInstructionSafe::Format FORMAT> HandleMovWide()328 bool HandleMovWide() 329 { 330 LOG_INST(); 331 DBGBRK(); 332 uint16_t vd = inst_.GetVReg<FORMAT, 0x00>(); 333 uint16_t vs = inst_.GetVReg<FORMAT, 0x01>(); 334 Sync(); 335 336 if (!CheckRegType(vs, bits64_)) { 337 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 338 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 339 return false; 340 } 341 AssignRegToReg(vd, vs); 342 MoveToNextInst<FORMAT>(); 343 return true; 344 } 345 346 template <BytecodeInstructionSafe::Format FORMAT> HandleMovObj()347 bool HandleMovObj() 348 { 349 LOG_INST(); 350 DBGBRK(); 351 uint16_t vd = inst_.GetVReg<FORMAT, 0x00>(); 352 uint16_t vs = inst_.GetVReg<FORMAT, 0x01>(); 353 Sync(); 354 if (!CheckRegType(vs, refType_)) { 355 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 356 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 357 return false; 358 } 359 AssignRegToReg(vd, vs); 360 MoveToNextInst<FORMAT>(); 361 return true; 362 } 363 364 template <BytecodeInstructionSafe::Format FORMAT> HandleMovDyn()365 bool HandleMovDyn() 366 { 367 LOG_INST(); 368 DBGBRK(); 369 Sync(); 370 LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented"; 371 status_ = VerificationStatus::ERROR; 372 return false; 373 } 374 375 template <BytecodeInstructionSafe::Format FORMAT> HandleNop()376 bool HandleNop() 377 { 378 LOG_INST(); 379 DBGBRK(); 380 Sync(); 381 MoveToNextInst<FORMAT>(); 382 return true; 383 } 384 385 template <BytecodeInstructionSafe::Format FORMAT> HandleMovi()386 bool HandleMovi() 387 { 388 LOG_INST(); 389 DBGBRK(); 390 uint16_t vd = inst_.GetVReg<FORMAT>(); 391 Sync(); 392 SetReg(vd, i32_); 393 MoveToNextInst<FORMAT>(); 394 return true; 395 } 396 397 template <BytecodeInstructionSafe::Format FORMAT> HandleMoviWide()398 bool HandleMoviWide() 399 { 400 LOG_INST(); 401 DBGBRK(); 402 uint16_t vd = inst_.GetVReg<FORMAT>(); 403 Sync(); 404 SetReg(vd, i64_); 405 MoveToNextInst<FORMAT>(); 406 return true; 407 } 408 409 template <BytecodeInstructionSafe::Format FORMAT> HandleFmovi()410 bool HandleFmovi() 411 { 412 LOG_INST(); 413 DBGBRK(); 414 uint16_t vd = inst_.GetVReg<FORMAT>(); 415 Sync(); 416 SetReg(vd, f32_); 417 MoveToNextInst<FORMAT>(); 418 return true; 419 } 420 421 template <BytecodeInstructionSafe::Format FORMAT> HandleFmoviWide()422 bool HandleFmoviWide() 423 { 424 LOG_INST(); 425 DBGBRK(); 426 uint16_t vd = inst_.GetVReg<FORMAT>(); 427 Sync(); 428 SetReg(vd, f64_); 429 MoveToNextInst<FORMAT>(); 430 return true; 431 } 432 433 template <BytecodeInstructionSafe::Format FORMAT> HandleMovNull()434 bool HandleMovNull() 435 { 436 LOG_INST(); 437 DBGBRK(); 438 uint16_t vd = inst_.GetVReg<FORMAT>(); 439 Sync(); 440 SetReg(vd, nullRefType_); 441 MoveToNextInst<FORMAT>(); 442 return true; 443 } 444 445 template <BytecodeInstructionSafe::Format FORMAT> HandleLda()446 bool HandleLda() 447 { 448 LOG_INST(); 449 DBGBRK(); 450 uint16_t vs = inst_.GetVReg<FORMAT>(); 451 Sync(); 452 if (!CheckRegType(vs, bits32_)) { 453 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 454 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 455 return false; 456 } 457 AssignAccToReg(vs); 458 MoveToNextInst<FORMAT>(); 459 return true; 460 } 461 462 template <BytecodeInstructionSafe::Format FORMAT> 463 bool HandleLdaDyn(); 464 465 template <BytecodeInstructionSafe::Format FORMAT> 466 bool HandleLdaiDyn(); 467 468 template <BytecodeInstructionSafe::Format FORMAT> HandleLdaWide()469 bool HandleLdaWide() 470 { 471 LOG_INST(); 472 DBGBRK(); 473 uint16_t vs = inst_.GetVReg<FORMAT>(); 474 Sync(); 475 if (!CheckRegType(vs, bits64_)) { 476 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 477 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 478 return false; 479 } 480 AssignAccToReg(vs); 481 MoveToNextInst<FORMAT>(); 482 return true; 483 } 484 485 template <BytecodeInstructionSafe::Format FORMAT> HandleLdaObj()486 bool HandleLdaObj() 487 { 488 LOG_INST(); 489 DBGBRK(); 490 uint16_t vs = inst_.GetVReg<FORMAT>(); 491 Sync(); 492 if (!CheckRegType(vs, refType_)) { 493 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 494 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 495 return false; 496 } 497 AssignAccToReg(vs); 498 MoveToNextInst<FORMAT>(); 499 return true; 500 } 501 502 template <BytecodeInstructionSafe::Format FORMAT> HandleLdai()503 bool HandleLdai() 504 { 505 LOG_INST(); 506 DBGBRK(); 507 Sync(); 508 SetAcc(i32_); 509 MoveToNextInst<FORMAT>(); 510 return true; 511 } 512 513 template <BytecodeInstructionSafe::Format FORMAT> HandleLdaiWide()514 bool HandleLdaiWide() 515 { 516 LOG_INST(); 517 DBGBRK(); 518 Sync(); 519 SetAcc(i64_); 520 MoveToNextInst<FORMAT>(); 521 return true; 522 } 523 524 template <BytecodeInstructionSafe::Format FORMAT> HandleFldai()525 bool HandleFldai() 526 { 527 LOG_INST(); 528 DBGBRK(); 529 Sync(); 530 SetAcc(f32_); 531 MoveToNextInst<FORMAT>(); 532 return true; 533 } 534 535 template <BytecodeInstructionSafe::Format FORMAT> HandleFldaiWide()536 bool HandleFldaiWide() 537 { 538 LOG_INST(); 539 DBGBRK(); 540 Sync(); 541 SetAcc(f64_); 542 MoveToNextInst<FORMAT>(); 543 return true; 544 } 545 546 template <BytecodeInstructionSafe::Format FORMAT> 547 bool HandleFldaiDyn(); 548 549 template <BytecodeInstructionSafe::Format FORMAT> HandleLdaStr()550 bool HandleLdaStr() 551 { 552 LOG_INST(); 553 DBGBRK(); 554 Sync(); 555 Type cachedType = GetCachedType(); 556 if (!cachedType.IsConsistent()) { 557 SET_STATUS_FOR_MSG(CannotResolveClassId, OK); 558 return false; 559 } 560 SetAcc(cachedType); 561 MoveToNextInst<FORMAT>(); 562 return true; 563 } 564 565 template <BytecodeInstructionSafe::Format FORMAT> HandleLdaConst()566 bool HandleLdaConst() 567 { 568 LOG_INST(); 569 DBGBRK(); 570 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 571 Sync(); 572 Type cachedType = GetCachedType(); 573 if (!cachedType.IsConsistent()) { 574 // NOTE(vdyadov): refactor to verifier-messages 575 LOG(ERROR, VERIFIER) << "Verifier error: HandleLdaConst cache error"; 576 status_ = VerificationStatus::ERROR; 577 return false; 578 } 579 SetReg(vd, cachedType); 580 MoveToNextInst<FORMAT>(); 581 return true; 582 } 583 584 template <BytecodeInstructionSafe::Format FORMAT> HandleLdaType()585 bool HandleLdaType() 586 { 587 LOG_INST(); 588 DBGBRK(); 589 Sync(); 590 Type cachedType = GetCachedType(); 591 if (!cachedType.IsConsistent()) { 592 SET_STATUS_FOR_MSG(CannotResolveClassId, OK); 593 return false; 594 } 595 if (cachedType != GetTypeSystem()->ClassClass()) { 596 LOG(ERROR, VERIFIER) << "LDA_TYPE type must be Class."; 597 return false; 598 } 599 SetAcc(GetTypeSystem()->ClassClass()); 600 MoveToNextInst<FORMAT>(); 601 return true; 602 } 603 604 template <BytecodeInstructionSafe::Format FORMAT> HandleLdaNull()605 bool HandleLdaNull() 606 { 607 LOG_INST(); 608 DBGBRK(); 609 Sync(); 610 SetAcc(nullRefType_); 611 MoveToNextInst<FORMAT>(); 612 return true; 613 } 614 615 template <BytecodeInstructionSafe::Format FORMAT> HandleSta()616 bool HandleSta() 617 { 618 LOG_INST(); 619 DBGBRK(); 620 uint16_t vd = inst_.GetVReg<FORMAT>(); 621 Sync(); 622 if (!CheckRegType(ACC, bits32_)) { 623 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 624 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 625 return false; 626 } 627 AssignRegToAcc(vd); 628 MoveToNextInst<FORMAT>(); 629 return true; 630 } 631 632 template <BytecodeInstructionSafe::Format FORMAT> 633 bool HandleStaDyn(); 634 635 template <BytecodeInstructionSafe::Format FORMAT> HandleStaWide()636 bool HandleStaWide() 637 { 638 LOG_INST(); 639 DBGBRK(); 640 uint16_t vd = inst_.GetVReg<FORMAT>(); 641 Sync(); 642 if (!CheckRegType(ACC, bits64_)) { 643 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 644 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 645 return false; 646 } 647 AssignRegToAcc(vd); 648 MoveToNextInst<FORMAT>(); 649 return true; 650 } 651 652 template <BytecodeInstructionSafe::Format FORMAT> HandleStaObj()653 bool HandleStaObj() 654 { 655 LOG_INST(); 656 DBGBRK(); 657 uint16_t vd = inst_.GetVReg<FORMAT>(); 658 Sync(); 659 if (!CheckRegType(ACC, refType_)) { 660 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 661 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 662 return false; 663 } 664 AssignRegToAcc(vd); 665 MoveToNextInst<FORMAT>(); 666 return true; 667 } 668 669 template <BytecodeInstructionSafe::Format FORMAT> HandleJmp()670 bool HandleJmp() 671 { 672 LOG_INST(); 673 DBGBRK(); 674 int32_t imm = inst_.GetImm<FORMAT>(); 675 Sync(); 676 ProcessBranching(imm); 677 return false; 678 } 679 680 template <BytecodeInstructionSafe::Format FORMAT> 681 bool HandleCmpWide(); 682 683 template <BytecodeInstructionSafe::Format FORMAT> 684 bool HandleUcmp(); 685 686 template <BytecodeInstructionSafe::Format FORMAT> 687 bool HandleUcmpWide(); 688 689 template <BytecodeInstructionSafe::Format FORMAT> 690 bool HandleFcmpl(); 691 692 template <BytecodeInstructionSafe::Format FORMAT> 693 bool HandleFcmplWide(); 694 695 template <BytecodeInstructionSafe::Format FORMAT> 696 bool HandleFcmpg(); 697 698 template <BytecodeInstructionSafe::Format FORMAT> 699 bool HandleFcmpgWide(); 700 701 template <BytecodeInstructionSafe::Format FORMAT> 702 bool HandleJeqz(); 703 704 template <BytecodeInstructionSafe::Format FORMAT> HandleJeqzObj()705 bool HandleJeqzObj() 706 { 707 LOG_INST(); 708 DBGBRK(); 709 auto imm = inst_.GetImm<FORMAT>(); 710 711 Sync(); 712 713 if (!CheckRegType(ACC, refType_)) { 714 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 715 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 716 return false; 717 } 718 719 // NOTE(vdyadov): think of two-pass absint, where we can catch const-null cases 720 721 auto type = GetRegType(ACC); 722 SetAccAndOthersOfSameOrigin(nullRefType_); 723 724 if (!ProcessBranching(imm)) { 725 return false; 726 } 727 728 SetAccAndOthersOfSameOrigin(type); 729 MoveToNextInst<FORMAT>(); 730 return true; 731 } 732 733 template <BytecodeInstructionSafe::Format FORMAT> 734 bool HandleJnez(); 735 736 template <BytecodeInstructionSafe::Format FORMAT> HandleJnezObj()737 bool HandleJnezObj() 738 { 739 LOG_INST(); 740 DBGBRK(); 741 auto imm = inst_.GetImm<FORMAT>(); 742 Sync(); 743 744 if (!CheckRegType(ACC, refType_)) { 745 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 746 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 747 return false; 748 } 749 750 if (!ProcessBranching(imm)) { 751 return false; 752 } 753 754 SetAccAndOthersOfSameOrigin(nullRefType_); 755 MoveToNextInst<FORMAT>(); 756 return true; 757 } 758 759 template <BytecodeInstructionSafe::Format FORMAT> 760 bool HandleJltz(); 761 762 template <BytecodeInstructionSafe::Format FORMAT> 763 bool HandleJgtz(); 764 765 template <BytecodeInstructionSafe::Format FORMAT> 766 bool HandleJlez(); 767 768 template <BytecodeInstructionSafe::Format FORMAT> 769 bool HandleJgez(); 770 771 template <BytecodeInstructionSafe::Format FORMAT> 772 bool HandleJeq(); 773 774 template <BytecodeInstructionSafe::Format FORMAT> HandleJeqObj()775 bool HandleJeqObj() 776 { 777 LOG_INST(); 778 DBGBRK(); 779 auto imm = inst_.GetImm<FORMAT>(); 780 uint16_t vs = inst_.GetVReg<FORMAT>(); 781 782 Sync(); 783 784 if (!CheckRegType(ACC, refType_)) { 785 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 786 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 787 return false; 788 } 789 790 if (!CheckRegType(vs, refType_)) { 791 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 792 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 793 return false; 794 } 795 796 if (!ProcessBranching(imm)) { 797 return false; 798 } 799 800 MoveToNextInst<FORMAT>(); 801 return true; 802 } 803 804 template <BytecodeInstructionSafe::Format FORMAT> 805 bool HandleJne(); 806 807 template <BytecodeInstructionSafe::Format FORMAT> HandleJneObj()808 bool HandleJneObj() 809 { 810 LOG_INST(); 811 DBGBRK(); 812 auto imm = inst_.GetImm<FORMAT>(); 813 uint16_t vs = inst_.GetVReg<FORMAT>(); 814 815 Sync(); 816 817 if (!CheckRegType(ACC, refType_)) { 818 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 819 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 820 return false; 821 } 822 823 if (!CheckRegType(vs, refType_)) { 824 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 825 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 826 return false; 827 } 828 829 if (!ProcessBranching(imm)) { 830 return false; 831 } 832 833 MoveToNextInst<FORMAT>(); 834 return true; 835 } 836 837 template <BytecodeInstructionSafe::Format FORMAT> 838 bool HandleJlt(); 839 840 template <BytecodeInstructionSafe::Format FORMAT> 841 bool HandleJgt(); 842 843 template <BytecodeInstructionSafe::Format FORMAT> 844 bool HandleJle(); 845 846 template <BytecodeInstructionSafe::Format FORMAT> 847 bool HandleJge(); 848 849 template <BytecodeInstructionSafe::Format FORMAT> 850 bool HandleAdd2(); 851 852 template <BytecodeInstructionSafe::Format FORMAT> 853 bool HandleAdd2Wide(); 854 855 template <BytecodeInstructionSafe::Format FORMAT> 856 bool HandleFadd2(); 857 858 template <BytecodeInstructionSafe::Format FORMAT> 859 bool HandleFadd2Wide(); 860 861 template <BytecodeInstructionSafe::Format FORMAT> 862 bool HandleSub2(); 863 864 template <BytecodeInstructionSafe::Format FORMAT> 865 bool HandleSub2Wide(); 866 867 template <BytecodeInstructionSafe::Format FORMAT> 868 bool HandleFsub2(); 869 870 template <BytecodeInstructionSafe::Format FORMAT> 871 bool HandleFsub2Wide(); 872 873 template <BytecodeInstructionSafe::Format FORMAT> 874 bool HandleMul2(); 875 876 template <BytecodeInstructionSafe::Format FORMAT> 877 bool HandleMul2Wide(); 878 879 template <BytecodeInstructionSafe::Format FORMAT> 880 bool HandleFmul2(); 881 882 template <BytecodeInstructionSafe::Format FORMAT> 883 bool HandleFmul2Wide(); 884 885 template <BytecodeInstructionSafe::Format FORMAT> 886 bool HandleFdiv2(); 887 888 template <BytecodeInstructionSafe::Format FORMAT> 889 bool HandleFdiv2Wide(); 890 891 template <BytecodeInstructionSafe::Format FORMAT> 892 bool HandleFmod2(); 893 894 template <BytecodeInstructionSafe::Format FORMAT> 895 bool HandleFmod2Wide(); 896 897 template <BytecodeInstructionSafe::Format FORMAT> 898 bool HandleAnd2(); 899 900 template <BytecodeInstructionSafe::Format FORMAT> 901 bool HandleAnd2Wide(); 902 903 template <BytecodeInstructionSafe::Format FORMAT> 904 bool HandleOr2(); 905 906 template <BytecodeInstructionSafe::Format FORMAT> 907 bool HandleOr2Wide(); 908 909 template <BytecodeInstructionSafe::Format FORMAT> 910 bool HandleXor2(); 911 912 template <BytecodeInstructionSafe::Format FORMAT> 913 bool HandleXor2Wide(); 914 915 template <BytecodeInstructionSafe::Format FORMAT> 916 bool HandleShl2(); 917 918 template <BytecodeInstructionSafe::Format FORMAT> 919 bool HandleShl2Wide(); 920 921 template <BytecodeInstructionSafe::Format FORMAT> 922 bool HandleShr2(); 923 924 template <BytecodeInstructionSafe::Format FORMAT> 925 bool HandleShr2Wide(); 926 927 template <BytecodeInstructionSafe::Format FORMAT> 928 bool HandleAshr2(); 929 930 template <BytecodeInstructionSafe::Format FORMAT> 931 bool HandleAshr2Wide(); 932 933 template <BytecodeInstructionSafe::Format FORMAT> 934 bool HandleDiv2(); 935 936 template <BytecodeInstructionSafe::Format FORMAT> 937 bool HandleDiv2Wide(); 938 939 template <BytecodeInstructionSafe::Format FORMAT> 940 bool HandleMod2(); 941 942 template <BytecodeInstructionSafe::Format FORMAT> 943 bool HandleMod2Wide(); 944 945 template <BytecodeInstructionSafe::Format FORMAT> 946 bool HandleDivu2(); 947 948 template <BytecodeInstructionSafe::Format FORMAT> 949 bool HandleDivu2Wide(); 950 951 template <BytecodeInstructionSafe::Format FORMAT> 952 bool HandleModu2(); 953 954 template <BytecodeInstructionSafe::Format FORMAT> 955 bool HandleModu2Wide(); 956 957 template <BytecodeInstructionSafe::Format FORMAT> 958 bool HandleAdd2v(); 959 960 template <BytecodeInstructionSafe::Format FORMAT> 961 bool HandleAdd2vWide(); 962 963 template <BytecodeInstructionSafe::Format FORMAT> 964 bool HandleFadd2v(); 965 966 template <BytecodeInstructionSafe::Format FORMAT> 967 bool HandleFadd2vWide(); 968 969 template <BytecodeInstructionSafe::Format FORMAT> 970 bool HandleSub2v(); 971 972 template <BytecodeInstructionSafe::Format FORMAT> 973 bool HandleSub2vWide(); 974 975 template <BytecodeInstructionSafe::Format FORMAT> 976 bool HandleFsub2v(); 977 978 template <BytecodeInstructionSafe::Format FORMAT> 979 bool HandleFsub2vWide(); 980 981 template <BytecodeInstructionSafe::Format FORMAT> 982 bool HandleMul2v(); 983 984 template <BytecodeInstructionSafe::Format FORMAT> 985 bool HandleMul2vWide(); 986 987 template <BytecodeInstructionSafe::Format FORMAT> 988 bool HandleFmul2v(); 989 990 template <BytecodeInstructionSafe::Format FORMAT> 991 bool HandleFmul2vWide(); 992 993 template <BytecodeInstructionSafe::Format FORMAT> 994 bool HandleFdiv2v(); 995 996 template <BytecodeInstructionSafe::Format FORMAT> 997 bool HandleFdiv2vWide(); 998 999 template <BytecodeInstructionSafe::Format FORMAT> 1000 bool HandleFmod2v(); 1001 1002 template <BytecodeInstructionSafe::Format FORMAT> 1003 bool HandleFmod2vWide(); 1004 1005 template <BytecodeInstructionSafe::Format FORMAT> 1006 bool HandleAnd2v(); 1007 1008 template <BytecodeInstructionSafe::Format FORMAT> 1009 bool HandleAnd2vWide(); 1010 1011 template <BytecodeInstructionSafe::Format FORMAT> 1012 bool HandleOr2v(); 1013 1014 template <BytecodeInstructionSafe::Format FORMAT> 1015 bool HandleOr2vWide(); 1016 1017 template <BytecodeInstructionSafe::Format FORMAT> 1018 bool HandleXor2v(); 1019 1020 template <BytecodeInstructionSafe::Format FORMAT> 1021 bool HandleXor2vWide(); 1022 1023 template <BytecodeInstructionSafe::Format FORMAT> 1024 bool HandleShl2v(); 1025 1026 template <BytecodeInstructionSafe::Format FORMAT> 1027 bool HandleShl2vWide(); 1028 1029 template <BytecodeInstructionSafe::Format FORMAT> 1030 bool HandleShr2v(); 1031 1032 template <BytecodeInstructionSafe::Format FORMAT> 1033 bool HandleShr2vWide(); 1034 1035 template <BytecodeInstructionSafe::Format FORMAT> 1036 bool HandleAshr2v(); 1037 1038 template <BytecodeInstructionSafe::Format FORMAT> 1039 bool HandleAshr2vWide(); 1040 1041 template <BytecodeInstructionSafe::Format FORMAT> 1042 bool HandleDiv2v(); 1043 1044 template <BytecodeInstructionSafe::Format FORMAT> 1045 bool HandleDiv2vWide(); 1046 1047 template <BytecodeInstructionSafe::Format FORMAT> 1048 bool HandleMod2v(); 1049 1050 template <BytecodeInstructionSafe::Format FORMAT> 1051 bool HandleMod2vWide(); 1052 1053 template <BytecodeInstructionSafe::Format FORMAT> 1054 bool HandleDivu2v(); 1055 1056 template <BytecodeInstructionSafe::Format FORMAT> 1057 bool HandleDivu2vWide(); 1058 1059 template <BytecodeInstructionSafe::Format FORMAT> 1060 bool HandleModu2v(); 1061 1062 template <BytecodeInstructionSafe::Format FORMAT> 1063 bool HandleModu2vWide(); 1064 1065 template <BytecodeInstructionSafe::Format FORMAT> 1066 bool HandleAdd(); 1067 1068 template <BytecodeInstructionSafe::Format FORMAT> 1069 bool HandleSub(); 1070 1071 template <BytecodeInstructionSafe::Format FORMAT> 1072 bool HandleMul(); 1073 1074 template <BytecodeInstructionSafe::Format FORMAT> 1075 bool HandleAnd(); 1076 1077 template <BytecodeInstructionSafe::Format FORMAT> 1078 bool HandleOr(); 1079 1080 template <BytecodeInstructionSafe::Format FORMAT> 1081 bool HandleXor(); 1082 1083 template <BytecodeInstructionSafe::Format FORMAT> 1084 bool HandleShl(); 1085 1086 template <BytecodeInstructionSafe::Format FORMAT> 1087 bool HandleShr(); 1088 1089 template <BytecodeInstructionSafe::Format FORMAT> 1090 bool HandleAshr(); 1091 1092 template <BytecodeInstructionSafe::Format FORMAT> 1093 bool HandleDiv(); 1094 1095 template <BytecodeInstructionSafe::Format FORMAT> 1096 bool HandleMod(); 1097 1098 template <BytecodeInstructionSafe::Format FORMAT> 1099 bool HandleAddv(); 1100 1101 template <BytecodeInstructionSafe::Format FORMAT> 1102 bool HandleSubv(); 1103 1104 template <BytecodeInstructionSafe::Format FORMAT> 1105 bool HandleMulv(); 1106 1107 template <BytecodeInstructionSafe::Format FORMAT> 1108 bool HandleAndv(); 1109 1110 template <BytecodeInstructionSafe::Format FORMAT> 1111 bool HandleOrv(); 1112 1113 template <BytecodeInstructionSafe::Format FORMAT> 1114 bool HandleXorv(); 1115 1116 template <BytecodeInstructionSafe::Format FORMAT> 1117 bool HandleShlv(); 1118 1119 template <BytecodeInstructionSafe::Format FORMAT> 1120 bool HandleShrv(); 1121 1122 template <BytecodeInstructionSafe::Format FORMAT> 1123 bool HandleAshrv(); 1124 1125 template <BytecodeInstructionSafe::Format FORMAT> 1126 bool HandleDivv(); 1127 1128 template <BytecodeInstructionSafe::Format FORMAT> 1129 bool HandleModv(); 1130 1131 template <BytecodeInstructionSafe::Format FORMAT> 1132 bool HandleAddi(); 1133 1134 template <BytecodeInstructionSafe::Format FORMAT> 1135 bool HandleSubi(); 1136 1137 template <BytecodeInstructionSafe::Format FORMAT> 1138 bool HandleMuli(); 1139 1140 template <BytecodeInstructionSafe::Format FORMAT> 1141 bool HandleAndi(); 1142 1143 template <BytecodeInstructionSafe::Format FORMAT> 1144 bool HandleOri(); 1145 1146 template <BytecodeInstructionSafe::Format FORMAT> 1147 bool HandleXori(); 1148 1149 template <BytecodeInstructionSafe::Format FORMAT> 1150 bool HandleShli(); 1151 1152 template <BytecodeInstructionSafe::Format FORMAT> 1153 bool HandleShri(); 1154 1155 template <BytecodeInstructionSafe::Format FORMAT> 1156 bool HandleAshri(); 1157 1158 template <BytecodeInstructionSafe::Format FORMAT> 1159 bool HandleDivi(); 1160 1161 template <BytecodeInstructionSafe::Format FORMAT> 1162 bool HandleModi(); 1163 1164 template <BytecodeInstructionSafe::Format FORMAT> 1165 bool HandleAddiv(); 1166 1167 template <BytecodeInstructionSafe::Format FORMAT> 1168 bool HandleSubiv(); 1169 1170 template <BytecodeInstructionSafe::Format FORMAT> 1171 bool HandleMuliv(); 1172 1173 template <BytecodeInstructionSafe::Format FORMAT> 1174 bool HandleAndiv(); 1175 1176 template <BytecodeInstructionSafe::Format FORMAT> 1177 bool HandleOriv(); 1178 1179 template <BytecodeInstructionSafe::Format FORMAT> 1180 bool HandleXoriv(); 1181 1182 template <BytecodeInstructionSafe::Format FORMAT> 1183 bool HandleShliv(); 1184 1185 template <BytecodeInstructionSafe::Format FORMAT> 1186 bool HandleShriv(); 1187 1188 template <BytecodeInstructionSafe::Format FORMAT> 1189 bool HandleAshriv(); 1190 1191 template <BytecodeInstructionSafe::Format FORMAT> 1192 bool HandleDiviv(); 1193 1194 template <BytecodeInstructionSafe::Format FORMAT> 1195 bool HandleModiv(); 1196 1197 template <BytecodeInstructionSafe::Format FORMAT> HandleNeg()1198 bool HandleNeg() 1199 { 1200 LOG_INST(); 1201 DBGBRK(); 1202 Sync(); 1203 return CheckUnaryOp<FORMAT>(integral32_, i32_); 1204 } 1205 1206 template <BytecodeInstructionSafe::Format FORMAT> HandleNegWide()1207 bool HandleNegWide() 1208 { 1209 LOG_INST(); 1210 DBGBRK(); 1211 Sync(); 1212 return CheckUnaryOp<FORMAT>(integral64_, i64_); 1213 } 1214 1215 template <BytecodeInstructionSafe::Format FORMAT> HandleFneg()1216 bool HandleFneg() 1217 { 1218 LOG_INST(); 1219 DBGBRK(); 1220 Sync(); 1221 return CheckUnaryOp<FORMAT>(f32_); 1222 } 1223 1224 template <BytecodeInstructionSafe::Format FORMAT> HandleFnegWide()1225 bool HandleFnegWide() 1226 { 1227 LOG_INST(); 1228 DBGBRK(); 1229 Sync(); 1230 return CheckUnaryOp<FORMAT>(f64_); 1231 } 1232 1233 template <BytecodeInstructionSafe::Format FORMAT> HandleNot()1234 bool HandleNot() 1235 { 1236 LOG_INST(); 1237 DBGBRK(); 1238 Sync(); 1239 return CheckUnaryOp<FORMAT>(integral32_); 1240 } 1241 1242 template <BytecodeInstructionSafe::Format FORMAT> HandleNotWide()1243 bool HandleNotWide() 1244 { 1245 LOG_INST(); 1246 DBGBRK(); 1247 Sync(); 1248 return CheckUnaryOp<FORMAT>(integral64_); 1249 } 1250 1251 template <BytecodeInstructionSafe::Format FORMAT> HandleInci()1252 bool HandleInci() 1253 { 1254 LOG_INST(); 1255 DBGBRK(); 1256 uint16_t vx = inst_.GetVReg<FORMAT>(); 1257 Sync(); 1258 if (!CheckRegType(vx, integral32_)) { 1259 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 1260 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 1261 return false; 1262 } 1263 MoveToNextInst<FORMAT>(); 1264 return true; 1265 } 1266 1267 template <BytecodeInstructionSafe::Format FORMAT> 1268 bool HandleI32toi64(); 1269 1270 template <BytecodeInstructionSafe::Format FORMAT> 1271 bool HandleI32toi16(); 1272 1273 template <BytecodeInstructionSafe::Format FORMAT> 1274 bool HandleI32tou16(); 1275 1276 template <BytecodeInstructionSafe::Format FORMAT> 1277 bool HandleI32toi8(); 1278 1279 template <BytecodeInstructionSafe::Format FORMAT> 1280 bool HandleI32tou8(); 1281 1282 template <BytecodeInstructionSafe::Format FORMAT> 1283 bool HandleI32tou1(); 1284 1285 template <BytecodeInstructionSafe::Format FORMAT> 1286 bool HandleI32tof32(); 1287 1288 template <BytecodeInstructionSafe::Format FORMAT> 1289 bool HandleI32tof64(); 1290 1291 template <BytecodeInstructionSafe::Format FORMAT> 1292 bool HandleU32toi64(); 1293 1294 template <BytecodeInstructionSafe::Format FORMAT> 1295 bool HandleU32toi16(); 1296 1297 template <BytecodeInstructionSafe::Format FORMAT> 1298 bool HandleU32tou16(); 1299 1300 template <BytecodeInstructionSafe::Format FORMAT> 1301 bool HandleU32toi8(); 1302 1303 template <BytecodeInstructionSafe::Format FORMAT> 1304 bool HandleU32tou8(); 1305 1306 template <BytecodeInstructionSafe::Format FORMAT> 1307 bool HandleU32tou1(); 1308 1309 template <BytecodeInstructionSafe::Format FORMAT> 1310 bool HandleU32tof32(); 1311 1312 template <BytecodeInstructionSafe::Format FORMAT> 1313 bool HandleU32tof64(); 1314 1315 template <BytecodeInstructionSafe::Format FORMAT> 1316 bool HandleI64toi32(); 1317 1318 template <BytecodeInstructionSafe::Format FORMAT> 1319 bool HandleI64tou1(); 1320 1321 template <BytecodeInstructionSafe::Format FORMAT> 1322 bool HandleI64tof32(); 1323 1324 template <BytecodeInstructionSafe::Format FORMAT> 1325 bool HandleI64tof64(); 1326 1327 template <BytecodeInstructionSafe::Format FORMAT> 1328 bool HandleU64toi32(); 1329 1330 template <BytecodeInstructionSafe::Format FORMAT> 1331 bool HandleU64tou32(); 1332 1333 template <BytecodeInstructionSafe::Format FORMAT> 1334 bool HandleU64tou1(); 1335 1336 template <BytecodeInstructionSafe::Format FORMAT> 1337 bool HandleU64tof32(); 1338 1339 template <BytecodeInstructionSafe::Format FORMAT> 1340 bool HandleU64tof64(); 1341 1342 template <BytecodeInstructionSafe::Format FORMAT> 1343 bool HandleF32tof64(); 1344 1345 template <BytecodeInstructionSafe::Format FORMAT> 1346 bool HandleF32toi32(); 1347 1348 template <BytecodeInstructionSafe::Format FORMAT> 1349 bool HandleF32toi64(); 1350 1351 template <BytecodeInstructionSafe::Format FORMAT> 1352 bool HandleF32tou32(); 1353 1354 template <BytecodeInstructionSafe::Format FORMAT> 1355 bool HandleF32tou64(); 1356 1357 template <BytecodeInstructionSafe::Format FORMAT> 1358 bool HandleF64tof32(); 1359 1360 template <BytecodeInstructionSafe::Format FORMAT> 1361 bool HandleF64toi64(); 1362 1363 template <BytecodeInstructionSafe::Format FORMAT> 1364 bool HandleF64toi32(); 1365 1366 template <BytecodeInstructionSafe::Format FORMAT> 1367 bool HandleF64tou64(); 1368 1369 template <BytecodeInstructionSafe::Format FORMAT> 1370 bool HandleF64tou32(); 1371 1372 template <BytecodeInstructionSafe::Format FORMAT> HandleCallPolymorphicShort()1373 bool HandleCallPolymorphicShort() 1374 { 1375 LOG_INST(); 1376 DBGBRK(); 1377 Sync(); 1378 MoveToNextInst<FORMAT>(); 1379 return true; 1380 } 1381 1382 template <BytecodeInstructionSafe::Format FORMAT> HandleCallPolymorphic()1383 bool HandleCallPolymorphic() 1384 { 1385 LOG_INST(); 1386 DBGBRK(); 1387 Sync(); 1388 MoveToNextInst<FORMAT>(); 1389 return true; 1390 } 1391 1392 template <BytecodeInstructionSafe::Format FORMAT> HandleCallPolymorphicRange()1393 bool HandleCallPolymorphicRange() 1394 { 1395 LOG_INST(); 1396 DBGBRK(); 1397 Sync(); 1398 // It is a runtime (not verifier) responibility to check the MethodHandle.invoke() 1399 // parameter types and throw the WrongMethodTypeException if need 1400 MoveToNextInst<FORMAT>(); 1401 return true; 1402 } 1403 1404 template <BytecodeInstructionSafe::Format FORMAT> HandleCallePolymorphicShort()1405 bool HandleCallePolymorphicShort() 1406 { 1407 LOG_INST(); 1408 DBGBRK(); 1409 Sync(); 1410 MoveToNextInst<FORMAT>(); 1411 return true; 1412 } 1413 1414 template <BytecodeInstructionSafe::Format FORMAT> HandleCallePolymorphic()1415 bool HandleCallePolymorphic() 1416 { 1417 LOG_INST(); 1418 DBGBRK(); 1419 Sync(); 1420 MoveToNextInst<FORMAT>(); 1421 return true; 1422 } 1423 1424 template <BytecodeInstructionSafe::Format FORMAT> HandleCallePolymorphicRange()1425 bool HandleCallePolymorphicRange() 1426 { 1427 LOG_INST(); 1428 DBGBRK(); 1429 Sync(); 1430 // It is a runtime (not verifier) responibility to check the MethodHandle.invokeExact() 1431 // parameter types and throw the WrongMethodTypeException if need 1432 MoveToNextInst<FORMAT>(); 1433 return true; 1434 } 1435 1436 template <BytecodeInstructionSafe::Format FORMAT> HandleLdarr8()1437 bool HandleLdarr8() 1438 { 1439 LOG_INST(); 1440 DBGBRK(); 1441 uint16_t vs = inst_.GetVReg<FORMAT>(); 1442 Sync(); 1443 return CheckArrayLoad<FORMAT>(vs, {u1_, i8_}); 1444 } 1445 1446 template <BytecodeInstructionSafe::Format FORMAT> HandleLdarr16()1447 bool HandleLdarr16() 1448 { 1449 LOG_INST(); 1450 DBGBRK(); 1451 uint16_t vs = inst_.GetVReg<FORMAT>(); 1452 Sync(); 1453 return CheckArrayLoad<FORMAT>(vs, {i16_}); 1454 } 1455 1456 template <BytecodeInstructionSafe::Format FORMAT> HandleLdarr()1457 bool HandleLdarr() 1458 { 1459 LOG_INST(); 1460 DBGBRK(); 1461 uint16_t vs = inst_.GetVReg<FORMAT>(); 1462 Sync(); 1463 return CheckArrayLoad<FORMAT>(vs, {i32_, u32_}); 1464 } 1465 1466 template <BytecodeInstructionSafe::Format FORMAT> HandleLdarrWide()1467 bool HandleLdarrWide() 1468 { 1469 LOG_INST(); 1470 DBGBRK(); 1471 uint16_t vs = inst_.GetVReg<FORMAT>(); 1472 Sync(); 1473 return CheckArrayLoad<FORMAT>(vs, {i64_, u64_}); 1474 } 1475 1476 template <BytecodeInstructionSafe::Format FORMAT> HandleLdarru8()1477 bool HandleLdarru8() 1478 { 1479 LOG_INST(); 1480 DBGBRK(); 1481 uint16_t vs = inst_.GetVReg<FORMAT>(); 1482 Sync(); 1483 return CheckArrayLoad<FORMAT>(vs, {u1_, u8_}); 1484 } 1485 1486 template <BytecodeInstructionSafe::Format FORMAT> HandleLdarru16()1487 bool HandleLdarru16() 1488 { 1489 LOG_INST(); 1490 DBGBRK(); 1491 uint16_t vs = inst_.GetVReg<FORMAT>(); 1492 Sync(); 1493 return CheckArrayLoad<FORMAT>(vs, {u16_}); 1494 } 1495 1496 template <BytecodeInstructionSafe::Format FORMAT> HandleFldarr32()1497 bool HandleFldarr32() 1498 { 1499 LOG_INST(); 1500 DBGBRK(); 1501 uint16_t vs = inst_.GetVReg<FORMAT>(); 1502 Sync(); 1503 return CheckArrayLoad<FORMAT>(vs, {f32_}); 1504 } 1505 1506 template <BytecodeInstructionSafe::Format FORMAT> HandleFldarrWide()1507 bool HandleFldarrWide() 1508 { 1509 LOG_INST(); 1510 DBGBRK(); 1511 uint16_t vs = inst_.GetVReg<FORMAT>(); 1512 Sync(); 1513 return CheckArrayLoad<FORMAT>(vs, {f64_}); 1514 } 1515 1516 template <BytecodeInstructionSafe::Format FORMAT> HandleLdarrObj()1517 bool HandleLdarrObj() 1518 { 1519 LOG_INST(); 1520 DBGBRK(); 1521 uint16_t vs = inst_.GetVReg<FORMAT>(); 1522 Sync(); 1523 if (!CheckRegType(ACC, integral32_)) { 1524 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 1525 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 1526 return false; 1527 } 1528 1529 if (!CheckRegType(vs, arrayType_)) { 1530 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 1531 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 1532 return false; 1533 } 1534 1535 auto regType = GetRegType(vs); 1536 if (regType == nullRefType_) { 1537 // NOTE(vdyadov): redesign next code, after support exception handlers, 1538 // treat it as always throw NPE 1539 SHOW_MSG(AlwaysNpe) 1540 LOG_VERIFIER_ALWAYS_NPE(vs); 1541 END_SHOW_MSG(); 1542 SetAcc(top_); 1543 SET_STATUS_FOR_MSG(AlwaysNpe, OK); 1544 return false; 1545 } 1546 1547 auto arrEltType = regType.GetArrayElementType(GetTypeSystem()); 1548 if (!IsSubtype(arrEltType, refType_, GetTypeSystem())) { 1549 SHOW_MSG(BadArrayElementType) 1550 LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE(ToString(arrEltType), ToString(refType_)); 1551 END_SHOW_MSG(); 1552 SET_STATUS_FOR_MSG(BadArrayElementType, WARNING); 1553 return false; 1554 } 1555 SetAcc(arrEltType); 1556 MoveToNextInst<FORMAT>(); 1557 return true; 1558 } 1559 1560 template <BytecodeInstructionSafe::Format FORMAT> HandleStarr8()1561 bool HandleStarr8() 1562 { 1563 LOG_INST(); 1564 DBGBRK(); 1565 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 1566 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 1567 Sync(); 1568 return CheckArrayStoreExact<FORMAT>(v1, v2, integral32_, {u1_, i8_, u8_}); 1569 } 1570 1571 template <BytecodeInstructionSafe::Format FORMAT> HandleStarr16()1572 bool HandleStarr16() 1573 { 1574 LOG_INST(); 1575 DBGBRK(); 1576 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 1577 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 1578 Sync(); 1579 return CheckArrayStoreExact<FORMAT>(v1, v2, integral32_, {i16_, u16_}); 1580 } 1581 1582 template <BytecodeInstructionSafe::Format FORMAT> HandleStarr()1583 bool HandleStarr() 1584 { 1585 LOG_INST(); 1586 DBGBRK(); 1587 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 1588 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 1589 Sync(); 1590 return CheckArrayStoreExact<FORMAT>(v1, v2, integral32_, {i32_, u32_}); 1591 } 1592 1593 template <BytecodeInstructionSafe::Format FORMAT> HandleStarrWide()1594 bool HandleStarrWide() 1595 { 1596 LOG_INST(); 1597 DBGBRK(); 1598 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 1599 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 1600 Sync(); 1601 return CheckArrayStoreExact<FORMAT>(v1, v2, integral64_, {i64_, u64_}); 1602 } 1603 1604 template <BytecodeInstructionSafe::Format FORMAT> HandleFstarr32()1605 bool HandleFstarr32() 1606 { 1607 LOG_INST(); 1608 DBGBRK(); 1609 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 1610 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 1611 Sync(); 1612 return CheckArrayStoreExact<FORMAT>(v1, v2, float32_, {f32_}); 1613 } 1614 1615 template <BytecodeInstructionSafe::Format FORMAT> HandleFstarrWide()1616 bool HandleFstarrWide() 1617 { 1618 LOG_INST(); 1619 DBGBRK(); 1620 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 1621 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 1622 Sync(); 1623 return CheckArrayStoreExact<FORMAT>(v1, v2, float64_, {f64_}); 1624 } 1625 1626 template <BytecodeInstructionSafe::Format FORMAT> HandleStarrObj()1627 bool HandleStarrObj() 1628 { 1629 LOG_INST(); 1630 DBGBRK(); 1631 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 1632 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 1633 Sync(); 1634 return CheckArrayStore<FORMAT>(v1, v2, refType_); 1635 } 1636 1637 template <BytecodeInstructionSafe::Format FORMAT> HandleLenarr()1638 bool HandleLenarr() 1639 { 1640 LOG_INST(); 1641 DBGBRK(); 1642 uint16_t vs = inst_.GetVReg<FORMAT>(); 1643 Sync(); 1644 if (!CheckRegType(vs, arrayType_)) { 1645 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 1646 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 1647 return false; 1648 } 1649 SetAcc(i32_); 1650 MoveToNextInst<FORMAT>(); 1651 return true; 1652 } 1653 1654 template <BytecodeInstructionSafe::Format FORMAT> HandleNewarr()1655 bool HandleNewarr() 1656 { 1657 LOG_INST(); 1658 DBGBRK(); 1659 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 1660 uint16_t vs = inst_.GetVReg<FORMAT, 1>(); 1661 Sync(); 1662 if (!CheckRegType(vs, integral32_)) { 1663 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 1664 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 1665 return false; 1666 } 1667 Type type = GetCachedType(); 1668 if (!type.IsConsistent()) { 1669 SET_STATUS_FOR_MSG(CannotResolveClassId, OK); 1670 return false; 1671 } 1672 SHOW_MSG(DebugType) 1673 LOG_VERIFIER_DEBUG_TYPE(ToString(type)); 1674 END_SHOW_MSG(); 1675 if (!IsSubtype(type, arrayType_, GetTypeSystem())) { 1676 // NOTE(vdyadov): implement StrictSubtypes function to not include array_type_ in output 1677 SHOW_MSG(ArrayOfNonArrayType) 1678 LOG_VERIFIER_ARRAY_OF_NON_ARRAY_TYPE(ToString(type)); 1679 END_SHOW_MSG(); 1680 SET_STATUS_FOR_MSG(ArrayOfNonArrayType, WARNING); 1681 return false; 1682 } 1683 SetReg(vd, type); 1684 MoveToNextInst<FORMAT>(); 1685 return true; 1686 } 1687 1688 template <BytecodeInstructionSafe::Format FORMAT> HandleNewobj()1689 bool HandleNewobj() 1690 { 1691 LOG_INST(); 1692 DBGBRK(); 1693 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 1694 Sync(); 1695 Type cachedType = GetCachedType(); 1696 if (!cachedType.IsConsistent()) { 1697 LOG(ERROR, VERIFIER) << "Verifier error: HandleNewobj cache error"; 1698 status_ = VerificationStatus::ERROR; 1699 return false; 1700 } 1701 SHOW_MSG(DebugType) 1702 LOG_VERIFIER_DEBUG_TYPE(ToString(cachedType)); 1703 END_SHOW_MSG(); 1704 if (!IsSubtype(cachedType, objectType_, GetTypeSystem())) { 1705 SHOW_MSG(ObjectOfNonObjectType) 1706 LOG_VERIFIER_OBJECT_OF_NON_OBJECT_TYPE(ToString(cachedType)); 1707 END_SHOW_MSG(); 1708 SET_STATUS_FOR_MSG(ObjectOfNonObjectType, WARNING); 1709 return false; 1710 } 1711 SetReg(vd, cachedType); 1712 MoveToNextInst<FORMAT>(); 1713 return true; 1714 } 1715 1716 template <BytecodeInstructionSafe::Format FORMAT> CheckCallCtor(Method const * ctor,Span<int> regs)1717 bool CheckCallCtor(Method const *ctor, Span<int> regs) 1718 { 1719 Type objType = TypeOfClass(ctor->GetClass()); 1720 1721 // NOTE(vdyadov): put under NDEBUG? 1722 { 1723 if (debugCtx->SkipVerificationOfCall(ctor->GetUniqId())) { 1724 SetAcc(objType); 1725 MoveToNextInst<FORMAT>(); 1726 return true; 1727 } 1728 } 1729 1730 auto ctorNameGetter = [&ctor]() { return ctor->GetFullName(); }; 1731 1732 bool check = CheckMethodArgs(ctorNameGetter, ctor, regs, objType); 1733 if (check) { 1734 SetAcc(objType); 1735 MoveToNextInst<FORMAT>(); 1736 } 1737 return check; 1738 } 1739 1740 template <BytecodeInstructionSafe::Format FORMAT> CheckCtor(Span<int> regs)1741 bool CheckCtor(Span<int> regs) 1742 { 1743 Type type = GetCachedType(); 1744 if (UNLIKELY(type.IsClass() && type.GetClass()->IsArrayClass())) { 1745 if (job_->IsMethodPresentForOffset(inst_.GetOffset())) { 1746 // Array constructors are synthetic methods; ClassLinker does not provide them. 1747 LOG(ERROR, VERIFIER) << "Verifier internal error: ArrayCtor should not be instantiated as method"; 1748 return false; 1749 } 1750 SHOW_MSG(DebugArrayConstructor) 1751 LOG_VERIFIER_DEBUG_ARRAY_CONSTRUCTOR(); 1752 END_SHOW_MSG(); 1753 return CheckArrayCtor<FORMAT>(type, regs); 1754 } 1755 1756 Method const *ctor = GetCachedMethod(); 1757 1758 if (!type.IsConsistent() || ctor == nullptr) { 1759 SET_STATUS_FOR_MSG(CannotResolveMethodId, OK); 1760 SET_STATUS_FOR_MSG(CannotResolveClassId, OK); 1761 return false; 1762 } 1763 1764 PandaString expectedName = ark::panda_file::GetCtorName(ctor->GetClass()->GetSourceLang()); 1765 if (!ctor->IsConstructor() || ctor->IsStatic() || expectedName != StringDataToString(ctor->GetName())) { 1766 SHOW_MSG(InitobjCallsNotConstructor) 1767 LOG_VERIFIER_INITOBJ_CALLS_NOT_CONSTRUCTOR(ctor->GetFullName()); 1768 END_SHOW_MSG(); 1769 SET_STATUS_FOR_MSG(InitobjCallsNotConstructor, WARNING); 1770 return false; 1771 } 1772 1773 SHOW_MSG(DebugConstructor) 1774 LOG_VERIFIER_DEBUG_CONSTRUCTOR(ctor->GetFullName()); 1775 END_SHOW_MSG(); 1776 1777 return CheckCallCtor<FORMAT>(ctor, regs); 1778 } 1779 1780 template <BytecodeInstructionSafe::Format FORMAT> HandleInitobj()1781 bool HandleInitobj() 1782 { 1783 LOG_INST(); 1784 DBGBRK(); 1785 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 1786 uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>(); 1787 uint16_t vs3 = inst_.GetVReg<FORMAT, 0x02>(); 1788 uint16_t vs4 = inst_.GetVReg<FORMAT, 0x03>(); 1789 Sync(); 1790 std::array<int, 4UL> regs {vs1, vs2, vs3, vs4}; 1791 return CheckCtor<FORMAT>(Span {regs}); 1792 } 1793 1794 template <BytecodeInstructionSafe::Format FORMAT> HandleInitobjShort()1795 bool HandleInitobjShort() 1796 { 1797 LOG_INST(); 1798 DBGBRK(); 1799 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 1800 uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>(); 1801 Sync(); 1802 std::array<int, 2UL> regs {vs1, vs2}; 1803 return CheckCtor<FORMAT>(Span {regs}); 1804 } 1805 1806 template <BytecodeInstructionSafe::Format FORMAT> HandleInitobjRange()1807 bool HandleInitobjRange() 1808 { 1809 LOG_INST(); 1810 DBGBRK(); 1811 uint16_t vs = inst_.GetVReg<FORMAT, 0x00>(); 1812 Sync(); 1813 std::vector<int> regs; 1814 for (auto regIdx = vs; ExecCtx().CurrentRegContext().IsRegDefined(regIdx); regIdx++) { 1815 regs.push_back(regIdx); 1816 } 1817 return CheckCtor<FORMAT>(Span {regs}); 1818 } 1819 GetFieldType()1820 Type GetFieldType() 1821 { 1822 const Field *field = GetCachedField(); 1823 1824 if (field == nullptr) { 1825 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 1826 return {}; 1827 } 1828 1829 ScopedChangeThreadStatus st {ManagedThread::GetCurrent(), ThreadStatus::RUNNING}; 1830 Job::ErrorHandler handler; 1831 auto typeCls = field->ResolveTypeClass(&handler); 1832 if (typeCls == nullptr) { 1833 return Type {}; 1834 } 1835 return Type {typeCls}; 1836 } 1837 GetFieldObject()1838 Type GetFieldObject() 1839 { 1840 Field const *field = GetCachedField(); 1841 1842 if (field == nullptr) { 1843 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 1844 return {}; 1845 } 1846 return TypeOfClass(field->GetClass()); 1847 } 1848 CheckFieldAccess(int regIdx,Type expectedFieldType,bool isStatic,bool isVolatile)1849 bool CheckFieldAccess(int regIdx, Type expectedFieldType, bool isStatic, bool isVolatile) 1850 { 1851 Field const *field = GetCachedField(); 1852 1853 if (field == nullptr) { 1854 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 1855 return false; 1856 } 1857 1858 if (!CheckFieldAccessStaticVolatile(isStatic, isVolatile, field)) { 1859 return false; 1860 } 1861 1862 Type fieldObjType = GetFieldObject(); 1863 Type fieldType = GetFieldType(); 1864 if (!fieldType.IsConsistent()) { 1865 LOG_VERIFIER_CANNOT_RESOLVE_FIELD_TYPE(GetFieldName(field)); 1866 return false; 1867 } 1868 1869 if (!isStatic) { 1870 if (!IsRegDefined(regIdx)) { 1871 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 1872 return false; 1873 } 1874 Type objType = GetRegType(regIdx); 1875 if (objType == nullRefType_) { 1876 // NOTE(vdyadov): redesign next code, after support exception handlers, 1877 // treat it as always throw NPE 1878 SHOW_MSG(AlwaysNpe) 1879 LOG_VERIFIER_ALWAYS_NPE(regIdx); 1880 END_SHOW_MSG(); 1881 SET_STATUS_FOR_MSG(AlwaysNpe, OK); 1882 return false; 1883 } 1884 if (!IsSubtype(objType, fieldObjType, GetTypeSystem())) { 1885 SHOW_MSG(InconsistentRegisterAndFieldTypes) 1886 LOG_VERIFIER_INCONSISTENT_REGISTER_AND_FIELD_TYPES(GetFieldName(field), regIdx, ToString(objType), 1887 ToString(fieldObjType)); 1888 END_SHOW_MSG(); 1889 SET_STATUS_FOR_MSG(InconsistentRegisterAndFieldTypes, WARNING); 1890 } 1891 } 1892 1893 if (!IsSubtype(fieldType, expectedFieldType, GetTypeSystem())) { 1894 SHOW_MSG(UnexpectedFieldType) 1895 LOG_VERIFIER_UNEXPECTED_FIELD_TYPE(GetFieldName(field), ToString(fieldType), ToString(expectedFieldType)); 1896 END_SHOW_MSG(); 1897 SET_STATUS_FOR_MSG(UnexpectedFieldType, WARNING); 1898 return false; 1899 } 1900 1901 return CheckFieldAccessPlugin(field); 1902 } 1903 1904 template <BytecodeInstructionSafe::Format FORMAT> 1905 bool ProcessFieldLoad(int regDest, int regSrc, Type expectedFieldType, bool isStatic, bool isVolatile = false) 1906 { 1907 if (!CheckFieldAccess(regSrc, expectedFieldType, isStatic, isVolatile)) { 1908 return false; 1909 } 1910 Field const *field = GetCachedField(); 1911 1912 if (field == nullptr) { 1913 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 1914 return false; 1915 } 1916 1917 auto type = GetFieldType(); 1918 if (!type.IsConsistent()) { 1919 return false; 1920 } 1921 SetReg(regDest, type); 1922 MoveToNextInst<FORMAT>(); 1923 return true; 1924 } 1925 1926 template <BytecodeInstructionSafe::Format FORMAT> ProcessFieldLoad(int regIdx,Type expectedFieldType,bool isStatic)1927 bool ProcessFieldLoad(int regIdx, Type expectedFieldType, bool isStatic) 1928 { 1929 return ProcessFieldLoad<FORMAT>(ACC, regIdx, expectedFieldType, isStatic); 1930 } 1931 1932 template <BytecodeInstructionSafe::Format FORMAT> ProcessFieldLoadVolatile(int regDest,int regSrc,Type expectedFieldType,bool isStatic)1933 bool ProcessFieldLoadVolatile(int regDest, int regSrc, Type expectedFieldType, bool isStatic) 1934 { 1935 return ProcessFieldLoad<FORMAT>(regDest, regSrc, expectedFieldType, isStatic, true); 1936 } 1937 1938 template <BytecodeInstructionSafe::Format FORMAT> ProcessFieldLoadVolatile(int regIdx,Type expectedFieldType,bool isStatic)1939 bool ProcessFieldLoadVolatile(int regIdx, Type expectedFieldType, bool isStatic) 1940 { 1941 return ProcessFieldLoadVolatile<FORMAT>(ACC, regIdx, expectedFieldType, isStatic); 1942 } 1943 1944 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobj()1945 bool HandleLdobj() 1946 { 1947 LOG_INST(); 1948 DBGBRK(); 1949 uint16_t vs = inst_.GetVReg<FORMAT>(); 1950 Sync(); 1951 return ProcessFieldLoad<FORMAT>(vs, bits32_, false); 1952 } 1953 1954 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjWide()1955 bool HandleLdobjWide() 1956 { 1957 LOG_INST(); 1958 DBGBRK(); 1959 uint16_t vs = inst_.GetVReg<FORMAT>(); 1960 Sync(); 1961 return ProcessFieldLoad<FORMAT>(vs, bits64_, false); 1962 } 1963 1964 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjObj()1965 bool HandleLdobjObj() 1966 { 1967 LOG_INST(); 1968 DBGBRK(); 1969 uint16_t vs = inst_.GetVReg<FORMAT>(); 1970 Sync(); 1971 return ProcessFieldLoad<FORMAT>(vs, refType_, false); 1972 } 1973 1974 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjV()1975 bool HandleLdobjV() 1976 { 1977 LOG_INST(); 1978 DBGBRK(); 1979 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 1980 uint16_t vs = inst_.GetVReg<FORMAT, 1>(); 1981 Sync(); 1982 return ProcessFieldLoad<FORMAT>(vd, vs, bits32_, false); 1983 } 1984 1985 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVWide()1986 bool HandleLdobjVWide() 1987 { 1988 LOG_INST(); 1989 DBGBRK(); 1990 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 1991 uint16_t vs = inst_.GetVReg<FORMAT, 1>(); 1992 Sync(); 1993 return ProcessFieldLoad<FORMAT>(vd, vs, bits64_, false); 1994 } 1995 1996 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVObj()1997 bool HandleLdobjVObj() 1998 { 1999 LOG_INST(); 2000 DBGBRK(); 2001 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 2002 uint16_t vs = inst_.GetVReg<FORMAT, 1>(); 2003 Sync(); 2004 return ProcessFieldLoad<FORMAT>(vd, vs, refType_, false); 2005 } 2006 2007 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVolatile()2008 bool HandleLdobjVolatile() 2009 { 2010 LOG_INST(); 2011 DBGBRK(); 2012 uint16_t vs = inst_.GetVReg<FORMAT>(); 2013 Sync(); 2014 return ProcessFieldLoadVolatile<FORMAT>(vs, bits32_, false); 2015 } 2016 2017 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVolatileWide()2018 bool HandleLdobjVolatileWide() 2019 { 2020 LOG_INST(); 2021 DBGBRK(); 2022 uint16_t vs = inst_.GetVReg<FORMAT>(); 2023 Sync(); 2024 return ProcessFieldLoadVolatile<FORMAT>(vs, bits64_, false); 2025 } 2026 2027 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVolatileObj()2028 bool HandleLdobjVolatileObj() 2029 { 2030 LOG_INST(); 2031 DBGBRK(); 2032 uint16_t vs = inst_.GetVReg<FORMAT>(); 2033 Sync(); 2034 return ProcessFieldLoadVolatile<FORMAT>(vs, refType_, false); 2035 } 2036 2037 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVolatileV()2038 bool HandleLdobjVolatileV() 2039 { 2040 LOG_INST(); 2041 DBGBRK(); 2042 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 2043 uint16_t vs = inst_.GetVReg<FORMAT, 1>(); 2044 Sync(); 2045 return ProcessFieldLoadVolatile<FORMAT>(vd, vs, bits32_, false); 2046 } 2047 2048 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVolatileVWide()2049 bool HandleLdobjVolatileVWide() 2050 { 2051 LOG_INST(); 2052 DBGBRK(); 2053 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 2054 uint16_t vs = inst_.GetVReg<FORMAT, 1>(); 2055 Sync(); 2056 return ProcessFieldLoadVolatile<FORMAT>(vd, vs, bits64_, false); 2057 } 2058 2059 template <BytecodeInstructionSafe::Format FORMAT> HandleLdobjVolatileVObj()2060 bool HandleLdobjVolatileVObj() 2061 { 2062 LOG_INST(); 2063 DBGBRK(); 2064 uint16_t vd = inst_.GetVReg<FORMAT, 0>(); 2065 uint16_t vs = inst_.GetVReg<FORMAT, 1>(); 2066 Sync(); 2067 return ProcessFieldLoadVolatile<FORMAT>(vd, vs, refType_, false); 2068 } 2069 2070 template <BytecodeInstructionSafe::Format FORMAT, bool IS_VOLATILE = false, typename Check> ProcessStoreField(int vs,int vd,Type expectedFieldType,bool isStatic,Check check)2071 bool ProcessStoreField(int vs, int vd, Type expectedFieldType, bool isStatic, Check check) 2072 { 2073 if (!CheckRegType(vs, expectedFieldType)) { 2074 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2075 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2076 return false; 2077 } 2078 2079 if (!CheckFieldAccess(vd, expectedFieldType, isStatic, IS_VOLATILE)) { 2080 return false; 2081 } 2082 2083 Field const *field = GetCachedField(); 2084 2085 if (field == nullptr) { 2086 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 2087 return false; 2088 } 2089 Type fieldType = GetFieldType(); 2090 if (!fieldType.IsConsistent()) { 2091 return false; 2092 } 2093 2094 Type vsType = GetRegType(vs); 2095 2096 CheckResult const &result = check(fieldType.ToTypeId(), vsType.ToTypeId()); 2097 if (result.status != VerificationStatus::OK) { 2098 LOG_VERIFIER_DEBUG_STORE_FIELD(GetFieldName(field), ToString(fieldType), ToString(vsType)); 2099 status_ = result.status; 2100 if (result.IsError()) { 2101 return false; 2102 } 2103 } 2104 2105 MoveToNextInst<FORMAT>(); 2106 return true; 2107 } 2108 2109 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobj(int vs,int vd,bool isStatic)2110 bool ProcessStobj(int vs, int vd, bool isStatic) 2111 { 2112 return ProcessStoreField<FORMAT>(vs, vd, bits32_, isStatic, CheckStobj); 2113 } 2114 2115 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobj(int vd,bool isStatic)2116 bool ProcessStobj(int vd, bool isStatic) 2117 { 2118 return ProcessStobj<FORMAT>(ACC, vd, isStatic); 2119 } 2120 2121 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjVolatile(int vs,int vd,bool isStatic)2122 bool ProcessStobjVolatile(int vs, int vd, bool isStatic) 2123 { 2124 return ProcessStoreField<FORMAT, true>(vs, vd, bits32_, isStatic, CheckStobj); 2125 } 2126 2127 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjVolatile(int vd,bool isStatic)2128 bool ProcessStobjVolatile(int vd, bool isStatic) 2129 { 2130 return ProcessStobjVolatile<FORMAT>(ACC, vd, isStatic); 2131 } 2132 2133 template <BytecodeInstructionSafe::Format FORMAT> HandleStobj()2134 bool HandleStobj() 2135 { 2136 LOG_INST(); 2137 DBGBRK(); 2138 uint16_t vd = inst_.GetVReg<FORMAT>(); 2139 Sync(); 2140 2141 return ProcessStobj<FORMAT>(vd, false); 2142 } 2143 2144 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjV()2145 bool HandleStobjV() 2146 { 2147 LOG_INST(); 2148 DBGBRK(); 2149 uint16_t vs = inst_.GetVReg<FORMAT, 0>(); 2150 uint16_t vd = inst_.GetVReg<FORMAT, 1>(); 2151 Sync(); 2152 2153 return ProcessStobj<FORMAT>(vs, vd, false); 2154 } 2155 2156 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVolatile()2157 bool HandleStobjVolatile() 2158 { 2159 LOG_INST(); 2160 DBGBRK(); 2161 uint16_t vd = inst_.GetVReg<FORMAT>(); 2162 Sync(); 2163 2164 return ProcessStobjVolatile<FORMAT>(vd, false); 2165 } 2166 2167 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVolatileV()2168 bool HandleStobjVolatileV() 2169 { 2170 LOG_INST(); 2171 DBGBRK(); 2172 uint16_t vs = inst_.GetVReg<FORMAT, 0>(); 2173 uint16_t vd = inst_.GetVReg<FORMAT, 1>(); 2174 Sync(); 2175 2176 return ProcessStobjVolatile<FORMAT>(vs, vd, false); 2177 } 2178 2179 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjWide(int vs,int vd,bool isStatic)2180 bool ProcessStobjWide(int vs, int vd, bool isStatic) 2181 { 2182 return ProcessStoreField<FORMAT>(vs, vd, bits64_, isStatic, CheckStobjWide); 2183 } 2184 2185 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjWide(int vd,bool isStatic)2186 bool ProcessStobjWide(int vd, bool isStatic) 2187 { 2188 return ProcessStobjWide<FORMAT>(ACC, vd, isStatic); 2189 } 2190 2191 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjVolatileWide(int vs,int vd,bool isStatic)2192 bool ProcessStobjVolatileWide(int vs, int vd, bool isStatic) 2193 { 2194 return ProcessStoreField<FORMAT, true>(vs, vd, bits64_, isStatic, CheckStobjWide); 2195 } 2196 2197 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjVolatileWide(int vd,bool isStatic)2198 bool ProcessStobjVolatileWide(int vd, bool isStatic) 2199 { 2200 return ProcessStobjVolatileWide<FORMAT>(ACC, vd, isStatic); 2201 } 2202 2203 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjWide()2204 bool HandleStobjWide() 2205 { 2206 LOG_INST(); 2207 DBGBRK(); 2208 uint16_t vd = inst_.GetVReg<FORMAT>(); 2209 Sync(); 2210 2211 return ProcessStobjWide<FORMAT>(vd, false); 2212 } 2213 2214 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVWide()2215 bool HandleStobjVWide() 2216 { 2217 LOG_INST(); 2218 DBGBRK(); 2219 uint16_t vs = inst_.GetVReg<FORMAT, 0>(); 2220 uint16_t vd = inst_.GetVReg<FORMAT, 1>(); 2221 Sync(); 2222 2223 return ProcessStobjWide<FORMAT>(vs, vd, false); 2224 } 2225 2226 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVolatileWide()2227 bool HandleStobjVolatileWide() 2228 { 2229 LOG_INST(); 2230 DBGBRK(); 2231 uint16_t vd = inst_.GetVReg<FORMAT>(); 2232 Sync(); 2233 2234 return ProcessStobjVolatileWide<FORMAT>(vd, false); 2235 } 2236 2237 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVolatileVWide()2238 bool HandleStobjVolatileVWide() 2239 { 2240 LOG_INST(); 2241 DBGBRK(); 2242 uint16_t vs = inst_.GetVReg<FORMAT, 0>(); 2243 uint16_t vd = inst_.GetVReg<FORMAT, 1>(); 2244 Sync(); 2245 2246 return ProcessStobjVolatileWide<FORMAT>(vs, vd, false); 2247 } 2248 2249 template <BytecodeInstructionSafe::Format FORMAT> 2250 bool ProcessStobjObj(int vs, int vd, bool isStatic, bool isVolatile = false) 2251 { 2252 if (!CheckFieldAccess(vd, refType_, isStatic, isVolatile)) { 2253 return false; 2254 } 2255 2256 Field const *field = GetCachedField(); 2257 2258 if (field == nullptr) { 2259 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 2260 return false; 2261 } 2262 2263 Type fieldType = GetFieldType(); 2264 if (!fieldType.IsConsistent()) { 2265 return false; 2266 } 2267 2268 if (!CheckRegType(vs, refType_)) { 2269 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2270 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2271 return false; 2272 } 2273 2274 Type vsType = GetRegType(vs); 2275 if (!IsSubtype(vsType, fieldType, GetTypeSystem())) { 2276 SHOW_MSG(BadAccumulatorType) 2277 LOG_VERIFIER_BAD_ACCUMULATOR_TYPE(ToString(vsType), ToString(fieldType)); 2278 END_SHOW_MSG(); 2279 SET_STATUS_FOR_MSG(BadAccumulatorType, WARNING); 2280 return false; 2281 } 2282 2283 MoveToNextInst<FORMAT>(); 2284 return true; 2285 } 2286 2287 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjObj(int vd,bool isStatic)2288 bool ProcessStobjObj(int vd, bool isStatic) 2289 { 2290 return ProcessStobjObj<FORMAT>(ACC, vd, isStatic); 2291 } 2292 2293 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjVolatileObj(int vs,int vd,bool isStatic)2294 bool ProcessStobjVolatileObj(int vs, int vd, bool isStatic) 2295 { 2296 return ProcessStobjObj<FORMAT>(vs, vd, isStatic, true); 2297 } 2298 2299 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjVolatileObj(int vd,bool isStatic)2300 bool ProcessStobjVolatileObj(int vd, bool isStatic) 2301 { 2302 return ProcessStobjVolatileObj<FORMAT>(ACC, vd, isStatic); 2303 } 2304 2305 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjObj()2306 bool HandleStobjObj() 2307 { 2308 LOG_INST(); 2309 DBGBRK(); 2310 uint16_t vd = inst_.GetVReg<FORMAT>(); 2311 Sync(); 2312 return ProcessStobjObj<FORMAT>(vd, false); 2313 } 2314 2315 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVObj()2316 bool HandleStobjVObj() 2317 { 2318 LOG_INST(); 2319 DBGBRK(); 2320 uint16_t vs = inst_.GetVReg<FORMAT, 0>(); 2321 uint16_t vd = inst_.GetVReg<FORMAT, 1>(); 2322 Sync(); 2323 return ProcessStobjObj<FORMAT>(vs, vd, false); 2324 } 2325 2326 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVolatileObj()2327 bool HandleStobjVolatileObj() 2328 { 2329 LOG_INST(); 2330 DBGBRK(); 2331 uint16_t vd = inst_.GetVReg<FORMAT>(); 2332 Sync(); 2333 return ProcessStobjVolatileObj<FORMAT>(vd, false); 2334 } 2335 2336 template <BytecodeInstructionSafe::Format FORMAT> HandleStobjVolatileVObj()2337 bool HandleStobjVolatileVObj() 2338 { 2339 LOG_INST(); 2340 DBGBRK(); 2341 uint16_t vs = inst_.GetVReg<FORMAT, 0>(); 2342 uint16_t vd = inst_.GetVReg<FORMAT, 1>(); 2343 Sync(); 2344 return ProcessStobjVolatileObj<FORMAT>(vs, vd, false); 2345 } 2346 2347 template <BytecodeInstructionSafe::Format FORMAT> HandleLdstatic()2348 bool HandleLdstatic() 2349 { 2350 LOG_INST(); 2351 DBGBRK(); 2352 Sync(); 2353 return ProcessFieldLoad<FORMAT>(INVALID_REG, bits32_, true); 2354 } 2355 2356 template <BytecodeInstructionSafe::Format FORMAT> HandleLdstaticWide()2357 bool HandleLdstaticWide() 2358 { 2359 LOG_INST(); 2360 DBGBRK(); 2361 Sync(); 2362 return ProcessFieldLoad<FORMAT>(INVALID_REG, bits64_, true); 2363 } 2364 2365 template <BytecodeInstructionSafe::Format FORMAT> HandleLdstaticObj()2366 bool HandleLdstaticObj() 2367 { 2368 LOG_INST(); 2369 DBGBRK(); 2370 Sync(); 2371 return ProcessFieldLoad<FORMAT>(INVALID_REG, refType_, true); 2372 } 2373 2374 template <BytecodeInstructionSafe::Format FORMAT> HandleLdstaticVolatile()2375 bool HandleLdstaticVolatile() 2376 { 2377 LOG_INST(); 2378 DBGBRK(); 2379 Sync(); 2380 return ProcessFieldLoadVolatile<FORMAT>(INVALID_REG, bits32_, true); 2381 } 2382 2383 template <BytecodeInstructionSafe::Format FORMAT> HandleLdstaticVolatileWide()2384 bool HandleLdstaticVolatileWide() 2385 { 2386 LOG_INST(); 2387 DBGBRK(); 2388 Sync(); 2389 return ProcessFieldLoadVolatile<FORMAT>(INVALID_REG, bits64_, true); 2390 } 2391 2392 template <BytecodeInstructionSafe::Format FORMAT> HandleLdstaticVolatileObj()2393 bool HandleLdstaticVolatileObj() 2394 { 2395 LOG_INST(); 2396 DBGBRK(); 2397 Sync(); 2398 return ProcessFieldLoadVolatile<FORMAT>(INVALID_REG, refType_, true); 2399 } 2400 2401 template <BytecodeInstructionSafe::Format FORMAT> HandleStstatic()2402 bool HandleStstatic() 2403 { 2404 LOG_INST(); 2405 DBGBRK(); 2406 Sync(); 2407 return ProcessStobj<FORMAT>(INVALID_REG, true); 2408 } 2409 2410 template <BytecodeInstructionSafe::Format FORMAT> HandleStstaticWide()2411 bool HandleStstaticWide() 2412 { 2413 LOG_INST(); 2414 DBGBRK(); 2415 Sync(); 2416 return ProcessStobjWide<FORMAT>(INVALID_REG, true); 2417 } 2418 2419 template <BytecodeInstructionSafe::Format FORMAT> HandleStstaticObj()2420 bool HandleStstaticObj() 2421 { 2422 LOG_INST(); 2423 DBGBRK(); 2424 Sync(); 2425 return ProcessStobjObj<FORMAT>(INVALID_REG, true); 2426 } 2427 2428 template <BytecodeInstructionSafe::Format FORMAT> HandleStstaticVolatile()2429 bool HandleStstaticVolatile() 2430 { 2431 LOG_INST(); 2432 DBGBRK(); 2433 Sync(); 2434 return ProcessStobjVolatile<FORMAT>(INVALID_REG, true); 2435 } 2436 2437 template <BytecodeInstructionSafe::Format FORMAT> HandleStstaticVolatileWide()2438 bool HandleStstaticVolatileWide() 2439 { 2440 LOG_INST(); 2441 DBGBRK(); 2442 Sync(); 2443 return ProcessStobjVolatileWide<FORMAT>(INVALID_REG, true); 2444 } 2445 2446 template <BytecodeInstructionSafe::Format FORMAT> HandleStstaticVolatileObj()2447 bool HandleStstaticVolatileObj() 2448 { 2449 LOG_INST(); 2450 DBGBRK(); 2451 Sync(); 2452 return ProcessStobjVolatileObj<FORMAT>(INVALID_REG, true); 2453 } 2454 2455 template <typename Check> CheckReturn(Type retType,Type accType,Check check)2456 bool CheckReturn(Type retType, Type accType, Check check) 2457 { 2458 TypeId retTypeId = retType.ToTypeId(); 2459 2460 PandaVector<Type> compatibleAccTypes; 2461 // NOTE (gogabr): why recompute each time? 2462 for (size_t accIdx = 0; accIdx < static_cast<size_t>(TypeId::REFERENCE) + 1; ++accIdx) { 2463 auto accTypeId = static_cast<TypeId>(accIdx); 2464 const CheckResult &info = check(retTypeId, accTypeId); 2465 if (!info.IsError()) { 2466 compatibleAccTypes.push_back(Type::FromTypeId(accTypeId)); 2467 } 2468 } 2469 2470 if (!CheckType(accType, primitive_) || accType == primitive_) { 2471 LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE(ToString(accType)); 2472 SET_STATUS_FOR_MSG(BadAccumulatorReturnValueType, WARNING); 2473 return false; 2474 } 2475 2476 TypeId accTypeId = accType.ToTypeId(); 2477 2478 const auto &result = check(retTypeId, accTypeId); 2479 2480 if (!result.IsOk()) { 2481 LogInnerMessage(result); 2482 if (result.IsError()) { 2483 LOG_VERIFIER_DEBUG_FUNCTION_RETURN_AND_ACCUMULATOR_TYPES_WITH_COMPATIBLE_TYPES( 2484 ToString(ReturnType()), ToString(accType), ToString(compatibleAccTypes)); 2485 } else { 2486 LOG_VERIFIER_DEBUG_FUNCTION_RETURN_AND_ACCUMULATOR_TYPES(ToString(ReturnType()), ToString(accType)); 2487 } 2488 } 2489 2490 status_ = result.status; 2491 return status_ != VerificationStatus::ERROR; 2492 } 2493 2494 template <BytecodeInstructionSafe::Format FORMAT> HandleReturn()2495 bool HandleReturn() 2496 { 2497 LOG_INST(); 2498 DBGBRK(); 2499 Sync(); 2500 2501 if (!CheckType(ReturnType(), bits32_)) { 2502 LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE("", ToString(ReturnType()), ToString(bits32_)); 2503 SET_STATUS_FOR_MSG(BadReturnInstructionType, WARNING); 2504 return false; 2505 } 2506 2507 if (!IsRegDefined(ACC)) { 2508 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2509 return false; 2510 } 2511 2512 // NOTE(vdyadov): handle LUB of compatible primitive types 2513 if (!CheckType(GetAccType(), bits32_)) { 2514 LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE(ToString(GetAccType())); 2515 SET_STATUS_FOR_MSG(BadAccumulatorReturnValueType, WARNING); 2516 } 2517 return false; 2518 } 2519 2520 template <BytecodeInstructionSafe::Format FORMAT> 2521 bool HandleReturnDyn(); 2522 2523 template <bool IS_LOAD> CheckFieldAccessByName(int regIdx,Type expectedFieldType)2524 bool CheckFieldAccessByName(int regIdx, [[maybe_unused]] Type expectedFieldType) 2525 { 2526 Field const *rawField = GetCachedField(); 2527 Type objType; 2528 2529 // currently all union type named access sites are encoded as “$NamedAccessMeta” class fields 2530 // at bytecode level, thus we do not have accurate union type info to verify each variables 2531 // so the current temporary solution would be to skip verification for union types.This 2532 // actually introduce insecure possibilities here. Accurate verification for union types 2533 // will need redesign for union types support in the future 2534 // 2535 // based on the above,here we skip: 2536 // 1. checking whether a field existed in the union or not 2537 // 2. skip checking member access violiations 2538 return CheckFieldAccessByNameStartCheck(regIdx, rawField, objType); 2539 } 2540 2541 template <BytecodeInstructionSafe::Format FORMAT> ProcessFieldLoadByName(int regSrc,Type expectedFieldType)2542 bool ProcessFieldLoadByName(int regSrc, Type expectedFieldType) 2543 { 2544 if (!CheckFieldAccessByName<true>(regSrc, expectedFieldType)) { 2545 return false; 2546 } 2547 Field const *field = GetCachedField(); 2548 2549 if (field == nullptr) { 2550 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 2551 return false; 2552 } 2553 2554 auto type = GetFieldType(); 2555 if (!type.IsConsistent()) { 2556 return false; 2557 } 2558 SetReg(ACC, type); 2559 MoveToNextInst<FORMAT>(); 2560 return true; 2561 } 2562 2563 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsLdobjName()2564 bool HandleEtsLdobjName() 2565 { 2566 LOG_INST(); 2567 DBGBRK(); 2568 uint16_t vs = inst_.GetVReg<FORMAT>(); 2569 Sync(); 2570 return ProcessFieldLoadByName<FORMAT>(vs, bits32_); 2571 } 2572 2573 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsLdobjNameWide()2574 bool HandleEtsLdobjNameWide() 2575 { 2576 LOG_INST(); 2577 DBGBRK(); 2578 uint16_t vs = inst_.GetVReg<FORMAT>(); 2579 Sync(); 2580 return ProcessFieldLoadByName<FORMAT>(vs, bits64_); 2581 } 2582 2583 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsLdobjNameObj()2584 bool HandleEtsLdobjNameObj() 2585 { 2586 LOG_INST(); 2587 DBGBRK(); 2588 uint16_t vs = inst_.GetVReg<FORMAT>(); 2589 Sync(); 2590 return ProcessFieldLoadByName<FORMAT>(vs, refType_); 2591 } 2592 2593 template <BytecodeInstructionSafe::Format FORMAT, typename Check> ProcessStoreFieldByName(int vd,Type expectedFieldType,Check check)2594 bool ProcessStoreFieldByName(int vd, Type expectedFieldType, Check check) 2595 { 2596 if (!CheckRegType(ACC, expectedFieldType)) { 2597 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2598 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2599 return false; 2600 } 2601 if (!CheckFieldAccessByName<false>(vd, expectedFieldType)) { 2602 return false; 2603 } 2604 2605 Field const *field = GetCachedField(); 2606 2607 if (field == nullptr) { 2608 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 2609 return false; 2610 } 2611 Type fieldType = GetFieldType(); 2612 if (!fieldType.IsConsistent()) { 2613 return false; 2614 } 2615 2616 Type vsType = GetRegType(ACC); 2617 2618 CheckResult const &result = check(fieldType.ToTypeId(), vsType.ToTypeId()); 2619 if (result.status != VerificationStatus::OK) { 2620 LOG_VERIFIER_DEBUG_STORE_FIELD(GetFieldName(field), ToString(fieldType), ToString(vsType)); 2621 status_ = result.status; 2622 if (result.IsError()) { 2623 return false; 2624 } 2625 } 2626 2627 MoveToNextInst<FORMAT>(); 2628 return true; 2629 } 2630 2631 template <BytecodeInstructionSafe::Format FORMAT> ProcessStobjObjByName(int vd)2632 bool ProcessStobjObjByName(int vd) 2633 { 2634 if (!CheckFieldAccessByName<false>(vd, refType_)) { 2635 return false; 2636 } 2637 2638 Field const *field = GetCachedField(); 2639 2640 if (field == nullptr) { 2641 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 2642 return false; 2643 } 2644 2645 Type fieldType = GetFieldType(); 2646 if (!fieldType.IsConsistent()) { 2647 return false; 2648 } 2649 2650 if (!CheckRegType(ACC, refType_)) { 2651 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2652 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2653 return false; 2654 } 2655 2656 Type vsType = GetRegType(ACC); 2657 if (!IsSubtype(vsType, fieldType, GetTypeSystem())) { 2658 SHOW_MSG(BadAccumulatorType) 2659 LOG_VERIFIER_BAD_ACCUMULATOR_TYPE(ToString(vsType), ToString(fieldType)); 2660 END_SHOW_MSG(); 2661 SET_STATUS_FOR_MSG(BadAccumulatorType, WARNING); 2662 return false; 2663 } 2664 2665 MoveToNextInst<FORMAT>(); 2666 return true; 2667 } 2668 2669 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsStobjName()2670 bool HandleEtsStobjName() 2671 { 2672 LOG_INST(); 2673 DBGBRK(); 2674 uint16_t vd = inst_.GetVReg<FORMAT>(); 2675 Sync(); 2676 2677 return ProcessStoreFieldByName<FORMAT>(vd, bits32_, CheckStobj); 2678 } 2679 2680 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsStobjNameWide()2681 bool HandleEtsStobjNameWide() 2682 { 2683 LOG_INST(); 2684 DBGBRK(); 2685 uint16_t vd = inst_.GetVReg<FORMAT>(); 2686 Sync(); 2687 2688 return ProcessStoreFieldByName<FORMAT>(vd, bits64_, CheckStobjWide); 2689 } 2690 2691 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsStobjNameObj()2692 bool HandleEtsStobjNameObj() 2693 { 2694 LOG_INST(); 2695 DBGBRK(); 2696 uint16_t vd = inst_.GetVReg<FORMAT>(); 2697 Sync(); 2698 return ProcessStobjObjByName<FORMAT>(vd); 2699 } 2700 2701 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsCallNameShort()2702 bool HandleEtsCallNameShort() 2703 { 2704 LOG_INST(); 2705 DBGBRK(); 2706 // NOTE issue(21892) support callbyname 2707 // This stub should be replaced with appropriate handler 2708 return false; 2709 } 2710 2711 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsCallName()2712 bool HandleEtsCallName() 2713 { 2714 LOG_INST(); 2715 DBGBRK(); 2716 // NOTE issue(21892) support callbyname 2717 // This stub should be replaced with appropriate handler 2718 return false; 2719 } 2720 2721 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsCallNameRange()2722 bool HandleEtsCallNameRange() 2723 { 2724 LOG_INST(); 2725 DBGBRK(); 2726 // NOTE issue(21892) support callbyname 2727 // This stub should be replaced with appropriate handler 2728 return false; 2729 } 2730 2731 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsLdnullvalue()2732 bool HandleEtsLdnullvalue() 2733 { 2734 LOG_INST(); 2735 DBGBRK(); 2736 Sync(); 2737 SetAcc(objectType_); 2738 MoveToNextInst<FORMAT>(); 2739 return true; 2740 } 2741 2742 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsMovnullvalue()2743 bool HandleEtsMovnullvalue() 2744 { 2745 LOG_INST(); 2746 DBGBRK(); 2747 uint16_t vd = inst_.GetVReg<FORMAT>(); 2748 Sync(); 2749 SetReg(vd, objectType_); 2750 MoveToNextInst<FORMAT>(); 2751 return true; 2752 } 2753 2754 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsIsnullvalue()2755 bool HandleEtsIsnullvalue() 2756 { 2757 LOG_INST(); 2758 DBGBRK(); 2759 Sync(); 2760 2761 if (!CheckRegType(ACC, refType_)) { 2762 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2763 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2764 return false; 2765 } 2766 SetAcc(i32_); 2767 2768 MoveToNextInst<FORMAT>(); 2769 return true; 2770 } 2771 2772 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsEqualityHelper(uint16_t v1,uint16_t v2)2773 bool HandleEtsEqualityHelper(uint16_t v1, uint16_t v2) 2774 { 2775 if (!CheckRegType(v1, refType_)) { 2776 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2777 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2778 return false; 2779 } 2780 if (!CheckRegType(v2, refType_)) { 2781 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2782 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2783 return false; 2784 } 2785 SetAcc(i32_); 2786 2787 MoveToNextInst<FORMAT>(); 2788 return true; 2789 } 2790 2791 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsEquals()2792 bool HandleEtsEquals() 2793 { 2794 LOG_INST(); 2795 DBGBRK(); 2796 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 2797 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 2798 Sync(); 2799 2800 return HandleEtsEqualityHelper<FORMAT>(v1, v2); 2801 } 2802 2803 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsStrictequals()2804 bool HandleEtsStrictequals() 2805 { 2806 LOG_INST(); 2807 DBGBRK(); 2808 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 2809 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 2810 Sync(); 2811 2812 return HandleEtsEqualityHelper<FORMAT>(v1, v2); 2813 } 2814 2815 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsTypeof()2816 bool HandleEtsTypeof() 2817 { 2818 LOG_INST(); 2819 DBGBRK(); 2820 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 2821 Sync(); 2822 2823 if (!CheckRegType(v1, refType_)) { 2824 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2825 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2826 return false; 2827 } 2828 SetAcc(GetTypeSystem()->StringClass()); 2829 2830 MoveToNextInst<FORMAT>(); 2831 return true; 2832 } 2833 2834 template <BytecodeInstructionSafe::Format FORMAT> HandleEtsIstrue()2835 bool HandleEtsIstrue() 2836 { 2837 LOG_INST(); 2838 DBGBRK(); 2839 uint16_t v = inst_.GetVReg<FORMAT, 0x00>(); 2840 Sync(); 2841 2842 if (!CheckRegType(v, refType_)) { 2843 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 2844 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2845 return false; 2846 } 2847 SetAcc(i32_); 2848 2849 MoveToNextInst<FORMAT>(); 2850 return true; 2851 } 2852 2853 template <BytecodeInstructionSafe::Format FORMAT> HandleReturnWide()2854 bool HandleReturnWide() 2855 { 2856 LOG_INST(); 2857 DBGBRK(); 2858 Sync(); 2859 2860 if (!CheckType(ReturnType(), bits64_)) { 2861 LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE(".64", ToString(ReturnType()), ToString(bits64_)); 2862 status_ = VerificationStatus::ERROR; 2863 return false; 2864 } 2865 2866 if (!IsRegDefined(ACC)) { 2867 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2868 return false; 2869 } 2870 2871 if (!CheckType(GetAccType(), bits64_)) { 2872 LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE(ToString(GetAccType())); 2873 status_ = VerificationStatus::ERROR; 2874 } 2875 return false; 2876 } 2877 2878 template <BytecodeInstructionSafe::Format FORMAT> HandleReturnObj()2879 bool HandleReturnObj() 2880 { 2881 LOG_INST(); 2882 DBGBRK(); 2883 Sync(); 2884 2885 if (!CheckType(ReturnType(), refType_)) { 2886 LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE(".obj", ToString(ReturnType()), ToString(refType_)); 2887 status_ = VerificationStatus::ERROR; 2888 return false; 2889 } 2890 2891 if (!IsRegDefined(ACC)) { 2892 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 2893 return false; 2894 } 2895 2896 auto accType = GetAccType(); 2897 if (!CheckType(accType, ReturnType())) { 2898 LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE_WITH_SUBTYPE(ToString(accType), ToString(ReturnType())); 2899 // NOTE(vdyadov) : after solving issues with set of types in LUB, uncomment next line 2900 status_ = VerificationStatus::WARNING; 2901 } 2902 2903 return false; 2904 } 2905 2906 template <BytecodeInstructionSafe::Format FORMAT> HandleReturnVoid()2907 bool HandleReturnVoid() 2908 { 2909 LOG_INST(); 2910 DBGBRK(); 2911 // NOTE(vdyadov): think of introducing void as of separate type, like null 2912 Sync(); 2913 2914 if (ReturnType() != Type::Top()) { 2915 LOG_VERIFIER_BAD_RETURN_VOID_INSTRUCTION_TYPE(ToString(ReturnType())); 2916 status_ = VerificationStatus::ERROR; 2917 } 2918 2919 return false; 2920 } 2921 2922 template <BytecodeInstructionSafe::Format FORMAT> HandleCheckcast()2923 bool HandleCheckcast() 2924 { 2925 LOG_INST(); 2926 DBGBRK(); 2927 Sync(); 2928 Type cachedType = GetCachedType(); 2929 if (!CheckCastArrayObjectRegDef(cachedType)) { 2930 return false; 2931 } 2932 auto accType = GetAccType(); 2933 // NOTE(vdyadov): remove this check after #2365 2934 if (!CheckCastRefArrayType(accType)) { 2935 return false; 2936 } 2937 2938 if (IsSubtype(accType, nullRefType_, GetTypeSystem())) { 2939 LOG_VERIFIER_ACCUMULATOR_ALWAYS_NULL(); 2940 SET_STATUS_FOR_MSG(AccumulatorAlwaysNull, OK); 2941 // Don't set types for "others of the same origin" when origin is null: n = null, a = n, b = n, a = 2942 // (NewType)x 2943 MoveToNextInst<FORMAT>(); 2944 return true; 2945 } 2946 2947 if (IsSubtype(accType, cachedType, GetTypeSystem())) { 2948 LOG_VERIFIER_REDUNDANT_CHECK_CAST(ToString(accType), ToString(cachedType)); 2949 SET_STATUS_FOR_MSG(RedundantCheckCast, OK); 2950 // Do not update register type to parent type as we loose details and can get errors on further flow 2951 MoveToNextInst<FORMAT>(); 2952 return true; 2953 } 2954 2955 if (IsSubtype(cachedType, arrayType_, GetTypeSystem())) { 2956 auto eltType = cachedType.GetArrayElementType(GetTypeSystem()); 2957 if (!IsSubtype(accType, arrayType_, GetTypeSystem()) && !IsSubtype(cachedType, accType, GetTypeSystem())) { 2958 LOG_VERIFIER_IMPOSSIBLE_CHECK_CAST(ToString(accType)); 2959 status_ = VerificationStatus::WARNING; 2960 } else if (IsSubtype(accType, arrayType_, GetTypeSystem())) { 2961 auto accEltType = accType.GetArrayElementType(GetTypeSystem()); 2962 if (accEltType.IsConsistent() && !IsSubtype(accEltType, eltType, GetTypeSystem()) && 2963 !IsSubtype(eltType, accEltType, GetTypeSystem())) { 2964 LOG_VERIFIER_IMPOSSIBLE_ARRAY_CHECK_CAST(ToString(accEltType)); 2965 SET_STATUS_FOR_MSG(ImpossibleArrayCheckCast, OK); 2966 } 2967 } 2968 } else if (TpIntersection(cachedType, accType, GetTypeSystem()) == bot_) { 2969 LOG_VERIFIER_INCOMPATIBLE_ACCUMULATOR_TYPE(ToString(accType)); 2970 SET_STATUS_FOR_MSG(IncompatibleAccumulatorType, OK); 2971 } 2972 2973 if (status_ == VerificationStatus::ERROR) { 2974 SetAcc(top_); 2975 return false; 2976 } 2977 2978 SetAccAndOthersOfSameOrigin(TpIntersection(cachedType, accType, GetTypeSystem())); 2979 2980 MoveToNextInst<FORMAT>(); 2981 return true; 2982 } 2983 2984 template <BytecodeInstructionSafe::Format FORMAT> HandleIsinstance()2985 bool HandleIsinstance() 2986 { 2987 LOG_INST(); 2988 DBGBRK(); 2989 Sync(); 2990 Type cachedType = GetCachedType(); 2991 if (!CheckInstanceConsistentArrayObjectRegDef(cachedType)) { 2992 return false; 2993 } 2994 2995 auto *plugin = job_->JobPlugin(); 2996 auto const *jobMethod = job_->JobMethod(); 2997 2998 if (!CheckInstanceClass(cachedType, plugin, jobMethod)) { 2999 return false; 3000 } 3001 3002 auto accType = GetAccType(); 3003 // NOTE(vdyadov): remove this check after #2365 3004 if (!IsSubtype(accType, refType_, GetTypeSystem()) && !IsSubtype(accType, arrayType_, GetTypeSystem())) { 3005 LOG_VERIFIER_NON_OBJECT_ACCUMULATOR_TYPE(); 3006 status_ = VerificationStatus::ERROR; 3007 return false; 3008 } 3009 3010 if (IsSubtype(accType, nullRefType_, GetTypeSystem())) { 3011 LOG_VERIFIER_ACCUMULATOR_ALWAYS_NULL(); 3012 SET_STATUS_FOR_MSG(AccumulatorAlwaysNull, OK); 3013 } else if (IsSubtype(accType, cachedType, GetTypeSystem())) { 3014 LOG_VERIFIER_REDUNDANT_IS_INSTANCE(ToString(accType), ToString(cachedType)); 3015 SET_STATUS_FOR_MSG(RedundantIsInstance, OK); 3016 } else if (IsSubtype(cachedType, arrayType_, GetTypeSystem())) { 3017 auto eltType = cachedType.GetArrayElementType(GetTypeSystem()); 3018 auto accEltType = accType.GetArrayElementType(GetTypeSystem()); 3019 bool accEltTypeIsEmpty = accEltType.IsConsistent(); 3020 if (!IsSubtype(accEltType, eltType, GetTypeSystem()) && !IsSubtype(eltType, accEltType, GetTypeSystem())) { 3021 if (accEltTypeIsEmpty) { 3022 LOG_VERIFIER_IMPOSSIBLE_IS_INSTANCE(ToString(accType)); 3023 SET_STATUS_FOR_MSG(ImpossibleIsInstance, OK); 3024 } else { 3025 LOG_VERIFIER_IMPOSSIBLE_ARRAY_IS_INSTANCE(ToString(accEltType)); 3026 SET_STATUS_FOR_MSG(ImpossibleArrayIsInstance, OK); 3027 } 3028 } 3029 } else if (TpIntersection(cachedType, accType, GetTypeSystem()) == bot_) { 3030 LOG_VERIFIER_IMPOSSIBLE_IS_INSTANCE(ToString(accType)); 3031 SET_STATUS_FOR_MSG(ImpossibleIsInstance, OK); 3032 } // else { 3033 // NOTE(vdyadov): here we may increase precision to concrete values in some cases 3034 SetAcc(i32_); 3035 MoveToNextInst<FORMAT>(); 3036 return true; 3037 } 3038 3039 template <typename NameGetter> 3040 bool CheckMethodArgs(NameGetter nameGetter, Method const *method, Span<int> regs, Type constructedType = Type {}) 3041 { 3042 auto const &formalArgs = GetTypeSystem()->GetMethodSignature(method)->args; 3043 if (formalArgs.empty()) { 3044 return true; 3045 } 3046 3047 size_t regsNeeded = !constructedType.IsNone() ? formalArgs.size() - 1 : formalArgs.size(); 3048 if (regs.size() < regsNeeded) { 3049 return CheckMethodArgsTooFewParmeters<NameGetter>(nameGetter); 3050 } 3051 auto sigIter = formalArgs.cbegin(); 3052 auto regsIter = regs.cbegin(); 3053 for (size_t argnum = 0; argnum < formalArgs.size(); argnum++) { 3054 auto regNum = (!constructedType.IsNone() && sigIter == formalArgs.cbegin()) ? INVALID_REG : *(regsIter++); 3055 auto formalType = *(sigIter++); 3056 3057 if (regNum != INVALID_REG && !IsRegDefined(regNum)) { 3058 LOG_VERIFIER_BAD_CALL_UNDEFINED_REGISTER(nameGetter(), regNum); 3059 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3060 return false; 3061 } 3062 Type actualType = regNum == INVALID_REG ? constructedType : GetRegType(regNum); 3063 // arg: NormalizedTypeOf(actual_type) <= norm_type 3064 // check of physical compatibility 3065 bool incompatibleTypes = false; 3066 if (CheckMethodArgsNotFit(formalType, actualType, regNum, incompatibleTypes)) { 3067 continue; 3068 } 3069 if (incompatibleTypes) { 3070 return CheckMethodArgsIncompatibleTypes<NameGetter>(nameGetter, regNum, actualType, formalType); 3071 } 3072 if (formalType == Type::Bot()) { 3073 return CheckMethodArgsBot<NameGetter>(nameGetter, actualType); 3074 } 3075 if (formalType == Type::Top()) { 3076 return CheckMethodArgsTop(actualType); 3077 } 3078 if (IsSubtype(formalType, primitive_, GetTypeSystem())) { 3079 if (!CheckMethodArgsSubtypePrimitive(nameGetter, formalType, actualType, regNum)) { 3080 return false; 3081 } 3082 continue; 3083 } 3084 if (!CheckType(actualType, formalType)) { 3085 CheckMethodArgsCheckType<NameGetter>(nameGetter, actualType, formalType, regNum); 3086 if (!config->opts.debug.allow.wrongSubclassingInMethodArgs) { 3087 status_ = VerificationStatus::ERROR; 3088 return false; 3089 } 3090 } 3091 } 3092 return true; 3093 } 3094 3095 template <BytecodeInstructionSafe::Format FORMAT> CheckCall(Method const * method,Span<int> regs)3096 bool CheckCall(Method const *method, Span<int> regs) 3097 { 3098 if (method == nullptr) { 3099 SET_STATUS_FOR_MSG(CannotResolveMethodId, OK); 3100 return false; 3101 } 3102 3103 auto *plugin = job_->JobPlugin(); 3104 auto const *jobMethod = job_->JobMethod(); 3105 auto result = plugin->CheckMethodAccessViolation(method, jobMethod, GetTypeSystem()); 3106 if (!result.IsOk()) { 3107 const auto &verifOpts = config->opts; 3108 if (verifOpts.debug.allow.methodAccessViolation && result.IsError()) { 3109 result.status = VerificationStatus::WARNING; 3110 } 3111 LogInnerMessage(result); 3112 LOG_VERIFIER_DEBUG_CALL_FROM_TO(job_->JobMethod()->GetFullName(), method->GetFullName()); 3113 status_ = result.status; 3114 if (status_ == VerificationStatus::ERROR) { 3115 return false; 3116 } 3117 } 3118 3119 const auto *methodSig = GetTypeSystem()->GetMethodSignature(method); 3120 auto methodNameGetter = [method]() { return method->GetFullName(); }; 3121 Type resultType = methodSig->result; 3122 3123 if (!debugCtx->SkipVerificationOfCall(method->GetUniqId()) && 3124 !CheckMethodArgs(methodNameGetter, method, regs)) { 3125 return false; 3126 } 3127 SetAcc(resultType); 3128 MoveToNextInst<FORMAT>(); 3129 return true; 3130 } 3131 3132 template <BytecodeInstructionSafe::Format FORMAT> HandleCallShort()3133 bool HandleCallShort() 3134 { 3135 LOG_INST(); 3136 DBGBRK(); 3137 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 3138 uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>(); 3139 Method const *method = GetCachedMethod(); 3140 if (method != nullptr) { 3141 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3142 } 3143 3144 if (method != nullptr && method->IsAbstract()) { 3145 LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName()); 3146 SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING); 3147 return false; 3148 } 3149 3150 Sync(); 3151 std::array<int, 2UL> regs {vs1, vs2}; 3152 return CheckCall<FORMAT>(method, Span {regs}); 3153 } 3154 3155 template <BytecodeInstructionSafe::Format FORMAT> HandleCallAccShort()3156 bool HandleCallAccShort() 3157 { 3158 LOG_INST(); 3159 DBGBRK(); 3160 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 3161 auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x00>()); 3162 static constexpr auto NUM_ARGS = 2; 3163 if (accPos >= NUM_ARGS) { 3164 LOG_VERIFIER_ACCUMULATOR_POSITION_IS_OUT_OF_RANGE(); 3165 SET_STATUS_FOR_MSG(AccumulatorPositionIsOutOfRange, WARNING); 3166 return status_ != VerificationStatus::ERROR; 3167 } 3168 Method const *method = GetCachedMethod(); 3169 if (method != nullptr) { 3170 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3171 } 3172 3173 if (method != nullptr && method->IsAbstract()) { 3174 LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName()); 3175 SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING); 3176 return false; 3177 } 3178 3179 Sync(); 3180 std::array<int, NUM_ARGS> regs {}; 3181 if (accPos == 0) { 3182 regs = {ACC, vs1}; 3183 } else { 3184 regs = {vs1, ACC}; 3185 } 3186 return CheckCall<FORMAT>(method, Span {regs}); 3187 } 3188 3189 template <BytecodeInstructionSafe::Format FORMAT> 3190 bool HandleCalliDynShort(); 3191 3192 template <BytecodeInstructionSafe::Format FORMAT> 3193 bool HandleCalliDyn(); 3194 3195 template <BytecodeInstructionSafe::Format FORMAT> 3196 bool HandleCalliDynRange(); 3197 3198 template <BytecodeInstructionSafe::Format FORMAT> HandleCall()3199 bool HandleCall() 3200 { 3201 LOG_INST(); 3202 DBGBRK(); 3203 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 3204 uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>(); 3205 uint16_t vs3 = inst_.GetVReg<FORMAT, 0x02>(); 3206 uint16_t vs4 = inst_.GetVReg<FORMAT, 0x03>(); 3207 Method const *method = GetCachedMethod(); 3208 if (method != nullptr) { 3209 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3210 } 3211 3212 if (method != nullptr && method->IsAbstract()) { 3213 LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName()); 3214 SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING); 3215 return false; 3216 } 3217 3218 Sync(); 3219 std::array<int, 4UL> regs {vs1, vs2, vs3, vs4}; 3220 return CheckCall<FORMAT>(method, Span {regs}); 3221 } 3222 3223 template <BytecodeInstructionSafe::Format FORMAT> HandleCallAcc()3224 bool HandleCallAcc() 3225 { 3226 LOG_INST(); 3227 DBGBRK(); 3228 auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x0>()); 3229 static constexpr auto NUM_ARGS = 4; 3230 if (accPos >= NUM_ARGS) { 3231 LOG_VERIFIER_ACCUMULATOR_POSITION_IS_OUT_OF_RANGE(); 3232 SET_STATUS_FOR_MSG(AccumulatorPositionIsOutOfRange, WARNING); 3233 return status_ != VerificationStatus::ERROR; 3234 } 3235 Method const *method = GetCachedMethod(); 3236 if (method != nullptr) { 3237 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3238 } 3239 3240 if (method != nullptr && method->IsAbstract()) { 3241 LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName()); 3242 SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING); 3243 return false; 3244 } 3245 3246 Sync(); 3247 std::array<int, NUM_ARGS> regs {}; 3248 auto regIdx = 0; 3249 for (unsigned i = 0; i < NUM_ARGS; ++i) { 3250 if (i == accPos) { 3251 regs[i] = ACC; 3252 } else { 3253 regs[i] = static_cast<int>(inst_.GetVReg(regIdx++)); 3254 } 3255 } 3256 return CheckCall<FORMAT>(method, Span {regs}); 3257 } 3258 3259 template <BytecodeInstructionSafe::Format FORMAT> HandleCallRange()3260 bool HandleCallRange() 3261 { 3262 LOG_INST(); 3263 DBGBRK(); 3264 uint16_t vs = inst_.GetVReg<FORMAT, 0x00>(); 3265 Method const *method = GetCachedMethod(); 3266 if (method != nullptr) { 3267 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3268 } 3269 3270 if (method != nullptr && method->IsAbstract()) { 3271 LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName()); 3272 SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING); 3273 return false; 3274 } 3275 3276 Sync(); 3277 std::vector<int> regs; 3278 for (auto regIdx = vs; ExecCtx().CurrentRegContext().IsRegDefined(regIdx); regIdx++) { 3279 regs.push_back(regIdx); 3280 } 3281 return CheckCall<FORMAT>(method, Span {regs}); 3282 } 3283 3284 template <BytecodeInstructionSafe::Format FORMAT> HandleCallVirtShort()3285 bool HandleCallVirtShort() 3286 { 3287 LOG_INST(); 3288 DBGBRK(); 3289 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 3290 uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>(); 3291 Method const *method = GetCachedMethod(); 3292 if (method != nullptr) { 3293 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3294 } 3295 if (method != nullptr && method->IsStatic()) { 3296 LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName()); 3297 SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING); 3298 return false; 3299 } 3300 3301 Sync(); 3302 std::array<int, 2UL> regs {vs1, vs2}; 3303 return CheckCall<FORMAT>(method, Span {regs}); 3304 } 3305 3306 template <BytecodeInstructionSafe::Format FORMAT> HandleCallVirtAccShort()3307 bool HandleCallVirtAccShort() 3308 { 3309 LOG_INST(); 3310 DBGBRK(); 3311 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 3312 auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x00>()); 3313 static constexpr auto NUM_ARGS = 2; 3314 Method const *method = GetCachedMethod(); 3315 if (method != nullptr) { 3316 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3317 } 3318 if (method != nullptr && method->IsStatic()) { 3319 LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName()); 3320 SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING); 3321 return false; 3322 } 3323 Sync(); 3324 std::array<int, NUM_ARGS> regs {}; 3325 if (accPos == 0) { 3326 regs = {ACC, vs1}; 3327 } else { 3328 regs = {vs1, ACC}; 3329 } 3330 return CheckCall<FORMAT>(method, Span {regs}); 3331 } 3332 3333 template <BytecodeInstructionSafe::Format FORMAT> HandleCallVirt()3334 bool HandleCallVirt() 3335 { 3336 LOG_INST(); 3337 DBGBRK(); 3338 uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>(); 3339 uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>(); 3340 uint16_t vs3 = inst_.GetVReg<FORMAT, 0x02>(); 3341 uint16_t vs4 = inst_.GetVReg<FORMAT, 0x03>(); 3342 Method const *method = GetCachedMethod(); 3343 if (method != nullptr) { 3344 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3345 } 3346 if (method != nullptr && method->IsStatic()) { 3347 LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName()); 3348 SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING); 3349 return false; 3350 } 3351 3352 Sync(); 3353 std::array<int, 4UL> regs {vs1, vs2, vs3, vs4}; 3354 return CheckCall<FORMAT>(method, Span {regs}); 3355 } 3356 3357 template <BytecodeInstructionSafe::Format FORMAT> HandleCallVirtAcc()3358 bool HandleCallVirtAcc() 3359 { 3360 LOG_INST(); 3361 DBGBRK(); 3362 auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x0>()); 3363 static constexpr auto NUM_ARGS = 4; 3364 Method const *method = GetCachedMethod(); 3365 if (method != nullptr) { 3366 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3367 } 3368 if (method != nullptr && method->IsStatic()) { 3369 LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName()); 3370 SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING); 3371 return false; 3372 } 3373 Sync(); 3374 std::array<int, NUM_ARGS> regs {}; 3375 auto regIdx = 0; 3376 for (unsigned i = 0; i < NUM_ARGS; ++i) { 3377 if (i == accPos) { 3378 regs[i] = ACC; 3379 } else { 3380 regs[i] = static_cast<int>(inst_.GetVReg(regIdx++)); 3381 } 3382 } 3383 return CheckCall<FORMAT>(method, Span {regs}); 3384 } 3385 3386 template <BytecodeInstructionSafe::Format FORMAT> HandleCallVirtRange()3387 bool HandleCallVirtRange() 3388 { 3389 LOG_INST(); 3390 DBGBRK(); 3391 uint16_t vs = inst_.GetVReg<FORMAT, 0x00>(); 3392 3393 Method const *method = GetCachedMethod(); 3394 if (method != nullptr) { 3395 LOG_VERIFIER_DEBUG_METHOD(method->GetFullName()); 3396 } 3397 if (method != nullptr && method->IsStatic()) { 3398 LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName()); 3399 SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING); 3400 return false; 3401 } 3402 3403 Sync(); 3404 std::vector<int> regs; 3405 for (auto regIdx = vs; ExecCtx().CurrentRegContext().IsRegDefined(regIdx); regIdx++) { 3406 regs.push_back(regIdx); 3407 } 3408 return CheckCall<FORMAT>(method, Span {regs}); 3409 } 3410 3411 template <BytecodeInstructionSafe::Format FORMAT> HandleThrow()3412 bool HandleThrow() 3413 { 3414 LOG_INST(); 3415 DBGBRK(); 3416 ExecCtx().SetCheckPoint(inst_.GetAddress()); 3417 Sync(); 3418 uint16_t vs = inst_.GetVReg<FORMAT>(); 3419 if (!CheckRegType(vs, GetTypeSystem()->Throwable())) { 3420 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3421 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3422 return false; 3423 } 3424 // possible implementation: 3425 // on stage of building checkpoints: 3426 // - add all catch block starts as checkpoints/entries 3427 // on absint stage: 3428 // - find corresponding catch block/checkpoint/entry 3429 // - add context to checkpoint/entry 3430 // - add entry to entry list 3431 // - stop absint 3432 return false; 3433 } 3434 3435 template <BytecodeInstructionSafe::Format FORMAT> HandleMonitorenter()3436 bool HandleMonitorenter() 3437 { 3438 LOG_INST(); 3439 DBGBRK(); 3440 Sync(); 3441 Type accType = GetAccType(); 3442 if (accType == nullRefType_) { 3443 // NOTE(vdyadov): redesign next code, after support exception handlers, 3444 // treat it as always throw NPE 3445 SHOW_MSG(AlwaysNpeAccumulator) 3446 LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR(); 3447 END_SHOW_MSG(); 3448 SET_STATUS_FOR_MSG(AlwaysNpeAccumulator, OK); 3449 return false; 3450 } 3451 if (!CheckType(accType, refType_)) { 3452 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3453 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3454 return false; 3455 } 3456 MoveToNextInst<FORMAT>(); 3457 return true; 3458 } 3459 3460 template <BytecodeInstructionSafe::Format FORMAT> HandleMonitorexit()3461 bool HandleMonitorexit() 3462 { 3463 LOG_INST(); 3464 DBGBRK(); 3465 Sync(); 3466 Type accType = GetAccType(); 3467 if (accType == nullRefType_) { 3468 // NOTE(vdyadov): redesign next code, after support exception handlers, 3469 // treat it as always throw NPE 3470 SHOW_MSG(AlwaysNpeAccumulator) 3471 LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR(); 3472 END_SHOW_MSG(); 3473 SET_STATUS_FOR_MSG(AlwaysNpeAccumulator, OK); 3474 return false; 3475 } 3476 if (!CheckType(accType, refType_)) { 3477 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3478 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3479 return false; 3480 } 3481 MoveToNextInst<FORMAT>(); 3482 return true; 3483 } 3484 GetInst()3485 BytecodeInstructionSafe GetInst() 3486 { 3487 return inst_; 3488 } 3489 3490 template <BytecodeInstructionSafe::Format FORMAT> HandleCallspecRange()3491 bool HandleCallspecRange() 3492 { 3493 // CallspecRange has the same semantics as CallRange in terms of 3494 // input and output for verification 3495 return HandleCallRange<FORMAT>(); 3496 } 3497 3498 static PandaString RegisterName(int regIdx, bool capitalize = false) 3499 { 3500 if (regIdx == ACC) { 3501 return capitalize ? "Accumulator" : "accumulator"; 3502 } 3503 return PandaString {capitalize ? "Register v" : "register v"} + NumToStr(regIdx); 3504 } 3505 3506 private: GetCachedType()3507 Type GetCachedType() const 3508 { 3509 auto offset = inst_.GetOffset(); 3510 if (!job_->IsTypePresentForOffset(offset)) { 3511 SHOW_MSG(CacheMissForClassAtOffset) 3512 LOG_VERIFIER_CACHE_MISS_FOR_CLASS_AT_OFFSET(offset); 3513 END_SHOW_MSG(); 3514 3515 SHOW_MSG(CannotResolveClassId) 3516 LOG_VERIFIER_CANNOT_RESOLVE_CLASS_ID(inst_.GetId().AsFileId().GetOffset()); 3517 END_SHOW_MSG(); 3518 return Type {}; 3519 } 3520 return job_->GetCachedType(offset); 3521 } 3522 GetCachedMethod()3523 Method const *GetCachedMethod() const 3524 { 3525 auto offset = inst_.GetOffset(); 3526 if (!job_->IsMethodPresentForOffset(offset)) { 3527 SHOW_MSG(CacheMissForMethodAtOffset) 3528 LOG_VERIFIER_CACHE_MISS_FOR_METHOD_AT_OFFSET(offset); 3529 END_SHOW_MSG(); 3530 3531 SHOW_MSG(CannotResolveMethodId) 3532 LOG_VERIFIER_CANNOT_RESOLVE_METHOD_ID(inst_.GetId().AsFileId().GetOffset()); 3533 END_SHOW_MSG(); 3534 return nullptr; 3535 } 3536 return job_->GetCachedMethod(offset); 3537 } 3538 GetCachedField()3539 Field const *GetCachedField() const 3540 { 3541 auto offset = inst_.GetOffset(); 3542 if (!job_->IsFieldPresentForOffset(offset)) { 3543 SHOW_MSG(CacheMissForFieldAtOffset) 3544 LOG_VERIFIER_CACHE_MISS_FOR_FIELD_AT_OFFSET(offset); 3545 END_SHOW_MSG(); 3546 3547 SHOW_MSG(CannotResolveFieldId) 3548 LOG_VERIFIER_CANNOT_RESOLVE_FIELD_ID(inst_.GetId().AsFileId().GetOffset()); 3549 END_SHOW_MSG(); 3550 return nullptr; 3551 } 3552 return job_->GetCachedField(offset); 3553 } 3554 3555 template <BytecodeInstructionSafe::Format FORMAT> MoveToNextInst()3556 void MoveToNextInst() 3557 { 3558 inst_ = inst_.GetNext<FORMAT>(); 3559 } 3560 3561 template <BytecodeInstructionSafe::Format FORMAT> CheckArrayStore(int v1,int v2,Type expectedEltType)3562 bool CheckArrayStore(int v1, int v2, Type expectedEltType) 3563 { 3564 /* 3565 main rules: 3566 1. instruction should be strict in array element size, so for primitive types type equality is used 3567 2. accumulator may be subtype of array element type (under question) 3568 */ 3569 if (!CheckRegType(v2, integral32_)) { 3570 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3571 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3572 return false; 3573 } 3574 if (!CheckRegType(v1, arrayType_)) { 3575 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3576 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3577 return false; 3578 } 3579 if (!IsRegDefined(ACC)) { 3580 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3581 return false; 3582 } 3583 Type regType = GetRegType(v1); 3584 if (regType == nullRefType_) { 3585 // NOTE(vdyadov): redesign next code, after support exception handlers, 3586 // treat it as always throw NPE 3587 SHOW_MSG(AlwaysNpe) 3588 LOG_VERIFIER_ALWAYS_NPE(v1); 3589 END_SHOW_MSG(); 3590 SetAcc(top_); 3591 SET_STATUS_FOR_MSG(AlwaysNpe, OK); 3592 return false; 3593 } 3594 3595 auto arrEltType = regType.GetArrayElementType(GetTypeSystem()); 3596 if (!IsSubtype(arrEltType, expectedEltType, GetTypeSystem())) { 3597 SHOW_MSG(BadArrayElementType2) 3598 LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE2(ToString(arrEltType), ToString(expectedEltType)); 3599 END_SHOW_MSG(); 3600 SET_STATUS_FOR_MSG(BadArrayElementType2, WARNING); 3601 return false; 3602 } 3603 3604 Type accType = GetAccType(); 3605 3606 // NOTE(dvyadov): think of subtyping here. Can we really write more precise type into array? 3607 // since there is no problems with storage (all refs are of the same size) 3608 // and no problems with information losses, it seems fine at first sight. 3609 bool res = !IsSubtype(accType, arrEltType, GetTypeSystem()); 3610 if (res) { 3611 // accumulator is of wrong type 3612 SHOW_MSG(BadAccumulatorType) 3613 LOG_VERIFIER_BAD_ACCUMULATOR_TYPE(ToString(accType), ToString(arrEltType)); 3614 END_SHOW_MSG(); 3615 SET_STATUS_FOR_MSG(BadAccumulatorType, WARNING); 3616 return false; 3617 } 3618 3619 MoveToNextInst<FORMAT>(); 3620 return true; 3621 } 3622 3623 template <BytecodeInstructionSafe::Format FORMAT> CheckArrayStoreExact(int v1,int v2,Type accSupertype,std::initializer_list<Type> const & expectedEltTypes)3624 bool CheckArrayStoreExact(int v1, int v2, Type accSupertype, std::initializer_list<Type> const &expectedEltTypes) 3625 { 3626 if (!CheckRegType(v2, integral32_) || !CheckRegType(v1, arrayType_) || !IsRegDefined(ACC)) { 3627 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3628 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3629 return false; 3630 } 3631 Type regType = GetRegType(v1); 3632 if (regType == nullRefType_) { 3633 SHOW_MSG(AlwaysNpe) 3634 LOG_VERIFIER_ALWAYS_NPE(v1); 3635 END_SHOW_MSG(); 3636 SetAcc(top_); 3637 SET_STATUS_FOR_MSG(AlwaysNpe, OK); 3638 return false; 3639 } 3640 3641 auto arrEltType = regType.GetArrayElementType(GetTypeSystem()); 3642 3643 auto find = [&expectedEltTypes](auto type) { 3644 // CC-OFFNXT(G.FMT.12) false positive 3645 return std::find(expectedEltTypes.begin(), expectedEltTypes.end(), type) != expectedEltTypes.end(); 3646 }; 3647 if (!find(arrEltType)) { 3648 // array elt type is not expected one 3649 PandaVector<Type> expectedTypesVec; 3650 for (auto et : expectedEltTypes) { 3651 expectedTypesVec.push_back(et); 3652 } 3653 LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE3(ToString(arrEltType), ToString(expectedTypesVec)); 3654 SET_STATUS_FOR_MSG(BadArrayElementType, WARNING); 3655 return false; 3656 } 3657 3658 Type accType = GetAccType(); 3659 if (!IsSubtype(accType, accSupertype, GetTypeSystem())) { 3660 LOG_VERIFIER_BAD_ACCUMULATOR_TYPE2(ToString(accType)); 3661 SET_STATUS_FOR_MSG(BadArrayElementType, WARNING); 3662 return false; 3663 } 3664 3665 if (!find(accType)) { 3666 // array elt type is not expected one 3667 PandaVector<Type> expectedTypesVec; 3668 expectedTypesVec.insert(expectedTypesVec.end(), expectedEltTypes.begin(), expectedEltTypes.end()); 3669 LOG_VERIFIER_BAD_ACCUMULATOR_TYPE3(ToString(accType), ToString(expectedTypesVec)); 3670 if (status_ != VerificationStatus::ERROR) { 3671 status_ = VerificationStatus::WARNING; 3672 } 3673 } 3674 3675 MoveToNextInst<FORMAT>(); 3676 return true; 3677 } 3678 3679 template <BytecodeInstructionSafe::Format FORMAT, bool REG_DST = false> CheckBinaryOp2(Type accIn,Type regIn,Type out)3680 bool CheckBinaryOp2(Type accIn, Type regIn, Type out) 3681 { 3682 uint16_t vs; 3683 if constexpr (REG_DST) { 3684 vs = inst_.GetVReg<FORMAT, 0x01>(); 3685 } else { 3686 vs = inst_.GetVReg<FORMAT>(); 3687 } 3688 if (!CheckRegType(ACC, accIn)) { 3689 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3690 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3691 return false; 3692 } 3693 if (!CheckRegType(vs, regIn)) { 3694 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3695 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3696 return false; 3697 } 3698 if constexpr (REG_DST) { 3699 SetReg(inst_.GetVReg<FORMAT, 0x00>(), out); 3700 } else { 3701 SetAcc(out); 3702 } 3703 MoveToNextInst<FORMAT>(); 3704 return true; 3705 } 3706 3707 template <BytecodeInstructionSafe::Format FORMAT, bool REG_DST = false> CheckBinaryOp2(Type accIn,Type regIn)3708 bool CheckBinaryOp2(Type accIn, Type regIn) 3709 { 3710 if (!IsRegDefined(ACC)) { 3711 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3712 return false; 3713 } 3714 return CheckBinaryOp2<FORMAT, REG_DST>(accIn, regIn, GetAccType()); 3715 } 3716 3717 template <BytecodeInstructionSafe::Format FORMAT> CheckBinaryOpImm(Type in,Type out)3718 bool CheckBinaryOpImm(Type in, Type out) 3719 { 3720 uint16_t vd = inst_.GetVReg<FORMAT, 0x00>(); 3721 uint16_t vs = inst_.GetVReg<FORMAT, 0x01>(); 3722 if (!CheckRegType(vs, in)) { 3723 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3724 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3725 return false; 3726 } 3727 SetReg(vd, out); 3728 MoveToNextInst<FORMAT>(); 3729 return true; 3730 } 3731 3732 template <BytecodeInstructionSafe::Format FORMAT> CheckBinaryOp2Imm(Type accIn,Type accOut)3733 bool CheckBinaryOp2Imm(Type accIn, Type accOut) 3734 { 3735 if (!CheckRegType(ACC, accIn)) { 3736 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3737 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3738 return false; 3739 } 3740 SetAcc(accOut); 3741 MoveToNextInst<FORMAT>(); 3742 return true; 3743 } 3744 3745 template <BytecodeInstructionSafe::Format FORMAT> CheckBinaryOp2Imm(Type accIn)3746 bool CheckBinaryOp2Imm(Type accIn) 3747 { 3748 if (!IsRegDefined(ACC)) { 3749 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3750 return false; 3751 } 3752 return CheckBinaryOp2Imm<FORMAT>(accIn, GetAccType()); 3753 } 3754 3755 template <BytecodeInstructionSafe::Format FORMAT> CheckUnaryOp(Type accIn,Type accOut)3756 bool CheckUnaryOp(Type accIn, Type accOut) 3757 { 3758 if (!CheckRegType(ACC, accIn)) { 3759 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3760 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3761 return false; 3762 } 3763 SetAcc(accOut); 3764 MoveToNextInst<FORMAT>(); 3765 return true; 3766 } 3767 3768 template <BytecodeInstructionSafe::Format FORMAT> CheckUnaryOp(Type accIn)3769 bool CheckUnaryOp(Type accIn) 3770 { 3771 if (!IsRegDefined(ACC)) { 3772 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3773 return false; 3774 } 3775 return CheckUnaryOp<FORMAT>(accIn, GetAccType()); 3776 } 3777 3778 template <BytecodeInstructionSafe::Format FORMAT, bool REG_DST = false> CheckBinaryOp(Type v1In,Type v2In,Type out)3779 bool CheckBinaryOp(Type v1In, Type v2In, Type out) 3780 { 3781 uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>(); 3782 uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>(); 3783 if (!CheckRegType(v1, v1In)) { 3784 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3785 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3786 return false; 3787 } 3788 if (!CheckRegType(v2, v2In)) { 3789 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3790 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3791 return false; 3792 } 3793 if constexpr (REG_DST) { 3794 SetReg(v1, out); 3795 } else { 3796 SetAcc(out); 3797 } 3798 MoveToNextInst<FORMAT>(); 3799 return true; 3800 } 3801 3802 template <BytecodeInstructionSafe::Format FORMAT> CheckBinaryOp(Type vs1In,Type vs2In)3803 bool CheckBinaryOp(Type vs1In, Type vs2In) 3804 { 3805 if (!IsRegDefined(ACC)) { 3806 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3807 return false; 3808 } 3809 return CheckBinaryOp<FORMAT>(vs1In, vs2In, GetAccType()); 3810 } 3811 3812 template <BytecodeInstructionSafe::Format FORMAT> HandleConversion(Type from,Type to)3813 bool HandleConversion(Type from, Type to) 3814 { 3815 if (!CheckRegType(ACC, from)) { 3816 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3817 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3818 return false; 3819 } 3820 SetAcc(to); 3821 MoveToNextInst<FORMAT>(); 3822 return true; 3823 } 3824 IsConcreteArrayType(Type type)3825 bool IsConcreteArrayType(Type type) 3826 { 3827 return IsSubtype(type, arrayType_, GetTypeSystem()) && type != arrayType_; 3828 } 3829 3830 template <BytecodeInstructionSafe::Format FORMAT> CheckArrayLoad(int vs,std::initializer_list<Type> const & expectedEltTypes)3831 bool CheckArrayLoad(int vs, std::initializer_list<Type> const &expectedEltTypes) 3832 { 3833 if (!CheckRegType(ACC, integral32_)) { 3834 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3835 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3836 return false; 3837 } 3838 if (!CheckRegType(vs, arrayType_)) { 3839 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3840 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3841 return false; 3842 } 3843 3844 Type regType = GetRegType(vs); 3845 if (regType == nullRefType_) { 3846 // NOTE(vdyadov): redesign next code, after support exception handlers, 3847 // treat it as always throw NPE 3848 SHOW_MSG(AlwaysNpe) 3849 LOG_VERIFIER_ALWAYS_NPE(vs); 3850 END_SHOW_MSG(); 3851 SetAcc(top_); 3852 SET_STATUS_FOR_MSG(AlwaysNpe, OK); 3853 return false; 3854 } 3855 auto &&arrEltType = regType.GetArrayElementType(GetTypeSystem()); 3856 auto find = [&expectedEltTypes](auto type) { 3857 for (Type t : expectedEltTypes) { 3858 if (type == t) { 3859 return true; 3860 } 3861 } 3862 return false; 3863 }; 3864 auto res = find(arrEltType); 3865 if (!res) { 3866 PandaVector<Type> expectedTypesVec; 3867 for (auto et : expectedEltTypes) { 3868 expectedTypesVec.push_back(et); 3869 } 3870 LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE3(ToString(arrEltType), ToString(expectedTypesVec)); 3871 SET_STATUS_FOR_MSG(BadArrayElementType, WARNING); 3872 return false; 3873 } 3874 SetAcc(arrEltType); 3875 MoveToNextInst<FORMAT>(); 3876 return true; 3877 } 3878 ProcessBranching(int32_t offset)3879 bool ProcessBranching(int32_t offset) 3880 { 3881 auto newInst = inst_.JumpTo(offset); 3882 const uint8_t *target = newInst.GetAddress(); 3883 if (!context_.CflowInfo().IsAddrValid(target) || 3884 !context_.CflowInfo().IsFlagSet(target, CflowMethodInfo::INSTRUCTION)) { 3885 LOG_VERIFIER_INCORRECT_JUMP(); 3886 status_ = VerificationStatus::ERROR; 3887 return false; 3888 } 3889 3890 #ifndef NDEBUG 3891 ExecCtx().ProcessJump( 3892 inst_.GetAddress(), target, 3893 [this, printHdr = true](int regIdx, const auto &srcReg, const auto &dstReg) mutable { 3894 if (printHdr) { 3895 LOG_VERIFIER_REGISTER_CONFLICT_HEADER(); 3896 printHdr = false; 3897 } 3898 LOG_VERIFIER_REGISTER_CONFLICT(RegisterName(regIdx), ToString(srcReg.GetAbstractType()), 3899 ToString(dstReg.GetAbstractType())); 3900 return true; 3901 }, 3902 codeType_); 3903 #else 3904 ExecCtx().ProcessJump(inst_.GetAddress(), target, codeType_); 3905 #endif 3906 return true; 3907 } 3908 3909 template <BytecodeInstructionSafe::Format FORMAT, template <typename OpT> class Op> HandleCondJmpz()3910 bool HandleCondJmpz() 3911 { 3912 auto imm = inst_.GetImm<FORMAT>(); 3913 3914 if (!CheckRegType(ACC, integral32_)) { 3915 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3916 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3917 return false; 3918 } 3919 3920 if (!ProcessBranching(imm)) { 3921 return false; 3922 } 3923 3924 MoveToNextInst<FORMAT>(); 3925 return true; 3926 } 3927 3928 template <BytecodeInstructionSafe::Format FORMAT, template <typename OpT> class Op> HandleCondJmp()3929 bool HandleCondJmp() 3930 { 3931 auto imm = inst_.GetImm<FORMAT>(); 3932 uint16_t vs = inst_.GetVReg<FORMAT>(); 3933 3934 if (!CheckRegType(ACC, integral32_)) { 3935 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3936 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3937 return false; 3938 } 3939 3940 if (!CheckRegType(vs, integral32_)) { 3941 SET_STATUS_FOR_MSG(BadRegisterType, WARNING); 3942 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3943 return false; 3944 } 3945 3946 if (!ProcessBranching(imm)) { 3947 return false; 3948 } 3949 3950 MoveToNextInst<FORMAT>(); 3951 return true; 3952 } 3953 3954 template <BytecodeInstructionSafe::Format FORMAT> CheckArrayCtor(Type klass,Span<int> regNums)3955 bool CheckArrayCtor(Type klass, Span<int> regNums) 3956 { 3957 if (!klass.IsConsistent() || !klass.IsClass() || !klass.GetClass()->IsArrayClass()) { 3958 return false; 3959 } 3960 auto argsNum = GetArrayNumDimensions(klass.GetClass()); 3961 bool result = false; 3962 for (auto reg : regNums) { 3963 if (!IsRegDefined(reg)) { 3964 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 3965 result = false; 3966 break; 3967 } 3968 result = CheckRegType(reg, i32_); 3969 if (!result) { 3970 LOG(ERROR, VERIFIER) << "Verifier error: ArrayCtor type error"; 3971 status_ = VerificationStatus::ERROR; 3972 break; 3973 } 3974 --argsNum; 3975 if (argsNum == 0) { 3976 break; 3977 } 3978 }; 3979 if (result && argsNum > 0) { 3980 SHOW_MSG(TooFewArrayConstructorArgs) 3981 LOG_VERIFIER_TOO_FEW_ARRAY_CONSTRUCTOR_ARGS(argsNum); 3982 END_SHOW_MSG(); 3983 SET_STATUS_FOR_MSG(TooFewArrayConstructorArgs, WARNING); 3984 result = false; 3985 } 3986 if (result) { 3987 SetAcc(klass); 3988 MoveToNextInst<FORMAT>(); 3989 } 3990 return result; 3991 } 3992 LogInnerMessage(const CheckResult & elt)3993 void LogInnerMessage(const CheckResult &elt) 3994 { 3995 if (elt.IsError()) { 3996 LOG(ERROR, VERIFIER) << "Error: " << elt.msg << ". "; 3997 } else if (elt.IsWarning()) { 3998 LOG(WARNING, VERIFIER) << "Warning: " << elt.msg << ". "; 3999 } 4000 } 4001 GetArrayNumDimensions(Class const * klass)4002 size_t GetArrayNumDimensions(Class const *klass) 4003 { 4004 size_t res = 0; 4005 while (klass->IsArrayClass()) { 4006 res++; 4007 klass = klass->GetComponentType(); 4008 } 4009 return res; 4010 } 4011 CheckFieldAccessStaticVolatile(bool isStatic,bool isVolatile,Field const * & field)4012 bool CheckFieldAccessStaticVolatile(bool isStatic, bool isVolatile, Field const *&field) 4013 { 4014 if (isStatic != field->IsStatic()) { 4015 SHOW_MSG(ExpectedStaticOrInstanceField) 4016 LOG_VERIFIER_EXPECTED_STATIC_OR_INSTANCE_FIELD(isStatic); 4017 END_SHOW_MSG(); 4018 SET_STATUS_FOR_MSG(ExpectedStaticOrInstanceField, WARNING); 4019 return false; 4020 } 4021 4022 if (isVolatile != field->IsVolatile()) { 4023 // if the inst is volatile but the field is not 4024 if (isVolatile) { 4025 SHOW_MSG(ExpectedVolatileField) 4026 LOG_VERIFIER_EXPECTED_VOLATILE_FIELD(); 4027 END_SHOW_MSG(); 4028 SET_STATUS_FOR_MSG(ExpectedVolatileField, WARNING); 4029 return false; 4030 } 4031 // if the instruction is not volatile but the field is 4032 SHOW_MSG(ExpectedInstanceField) 4033 LOG_VERIFIER_EXPECTED_INSTANCE_FIELD(); 4034 END_SHOW_MSG(); 4035 SET_STATUS_FOR_MSG(ExpectedInstanceField, ERROR); 4036 return false; 4037 } 4038 4039 return true; 4040 } 4041 CheckFieldAccessPlugin(Field const * & field)4042 bool CheckFieldAccessPlugin(Field const *&field) 4043 { 4044 auto *plugin = job_->JobPlugin(); 4045 auto const *jobMethod = job_->JobMethod(); 4046 auto result = plugin->CheckFieldAccessViolation(field, jobMethod, GetTypeSystem()); 4047 if (!result.IsOk()) { 4048 const auto &verifOpts = config->opts; 4049 if (verifOpts.debug.allow.fieldAccessViolation && result.IsError()) { 4050 result.status = VerificationStatus::WARNING; 4051 } 4052 LogInnerMessage(result); 4053 LOG_VERIFIER_DEBUG_FIELD2(GetFieldName(field)); 4054 status_ = result.status; 4055 return status_ != VerificationStatus::ERROR; 4056 } 4057 4058 return !result.IsError(); 4059 } 4060 CheckFieldAccessByNameStartCheck(int regIdx,Field const * & rawField,Type & objType)4061 bool CheckFieldAccessByNameStartCheck(int regIdx, Field const *&rawField, Type &objType) 4062 { 4063 if (rawField == nullptr) { 4064 SET_STATUS_FOR_MSG(CannotResolveFieldId, OK); 4065 return false; 4066 } 4067 4068 if (rawField->IsStatic()) { 4069 SHOW_MSG(ExpectedStaticOrInstanceField) 4070 LOG_VERIFIER_EXPECTED_STATIC_OR_INSTANCE_FIELD(false); 4071 END_SHOW_MSG(); 4072 SET_STATUS_FOR_MSG(ExpectedStaticOrInstanceField, WARNING); 4073 return false; 4074 } 4075 4076 if (!GetFieldType().IsConsistent()) { 4077 LOG_VERIFIER_CANNOT_RESOLVE_FIELD_TYPE(GetFieldName(rawField)); 4078 return false; 4079 } 4080 4081 if (!IsRegDefined(regIdx)) { 4082 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 4083 return false; 4084 } 4085 objType = GetRegType(regIdx); 4086 if (objType == nullRefType_) { 4087 // NOTE(vdyadov): redesign next code, after support exception handlers, 4088 // treat it as always throw NPE 4089 SHOW_MSG(AlwaysNpe) 4090 LOG_VERIFIER_ALWAYS_NPE(regIdx); 4091 END_SHOW_MSG(); 4092 SET_STATUS_FOR_MSG(AlwaysNpe, OK); 4093 return false; 4094 } 4095 4096 if (!objType.IsClass()) { 4097 SHOW_MSG(BadRegisterType) 4098 LOG_VERIFIER_BAD_REGISTER_CLASS_TYPE(RegisterName(regIdx, true), ToString(objType)); 4099 END_SHOW_MSG(); 4100 return false; 4101 } 4102 4103 return true; 4104 } 4105 CheckCastArrayObjectRegDef(Type & cachedType)4106 bool CheckCastArrayObjectRegDef(Type &cachedType) 4107 { 4108 if (!cachedType.IsConsistent()) { 4109 return false; 4110 } 4111 LOG_VERIFIER_DEBUG_TYPE(ToString(cachedType)); 4112 if (!IsSubtype(cachedType, objectType_, GetTypeSystem()) && 4113 !IsSubtype(cachedType, arrayType_, GetTypeSystem())) { 4114 LOG_VERIFIER_CHECK_CAST_TO_NON_OBJECT_TYPE(ToString(cachedType)); 4115 SET_STATUS_FOR_MSG(CheckCastToNonObjectType, WARNING); 4116 return false; 4117 } 4118 if (!IsRegDefined(ACC)) { 4119 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 4120 return false; 4121 } 4122 4123 return true; 4124 } 4125 CheckCastRefArrayType(Type & accType)4126 bool CheckCastRefArrayType(Type &accType) 4127 { 4128 if (!IsSubtype(accType, refType_, GetTypeSystem()) && !IsSubtype(accType, arrayType_, GetTypeSystem())) { 4129 LOG_VERIFIER_NON_OBJECT_ACCUMULATOR_TYPE(); 4130 SET_STATUS_FOR_MSG(NonObjectAccumulatorType, WARNING); 4131 return false; 4132 } 4133 4134 return true; 4135 } 4136 CheckInstanceConsistentArrayObjectRegDef(Type & cachedType)4137 bool CheckInstanceConsistentArrayObjectRegDef(Type &cachedType) 4138 { 4139 if (!cachedType.IsConsistent()) { 4140 return false; 4141 } 4142 LOG_VERIFIER_DEBUG_TYPE(ToString(cachedType)); 4143 if (!IsSubtype(cachedType, objectType_, GetTypeSystem()) && 4144 !IsSubtype(cachedType, arrayType_, GetTypeSystem())) { 4145 // !(type <= Types().ArrayType()) is redundant, because all arrays 4146 // are subtypes of either panda.Object <: ObjectType or java.lang.Object <: ObjectType 4147 // depending on selected language context 4148 LOG_VERIFIER_BAD_IS_INSTANCE_INSTRUCTION(ToString(cachedType)); 4149 SET_STATUS_FOR_MSG(BadIsInstanceInstruction, WARNING); 4150 return false; 4151 } 4152 if (!IsRegDefined(ACC)) { 4153 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING); 4154 return false; 4155 } 4156 4157 return true; 4158 } 4159 CheckInstanceClass(Type & cachedType,const plugin::Plugin * & plugin,Method const * & jobMethod)4160 bool CheckInstanceClass(Type &cachedType, const plugin::Plugin *&plugin, Method const *&jobMethod) 4161 { 4162 auto result = CheckResult::ok; 4163 if (cachedType.IsClass()) { 4164 result = plugin->CheckClassAccessViolation(cachedType.GetClass(), jobMethod, GetTypeSystem()); 4165 } 4166 if (!result.IsOk()) { 4167 LogInnerMessage(CheckResult::protected_class); 4168 LOG_VERIFIER_DEBUG_CALL_FROM_TO(job_->JobMethod()->GetClass()->GetName(), ToString(cachedType)); 4169 status_ = VerificationStatus::ERROR; 4170 return false; 4171 } 4172 4173 return true; 4174 } 4175 4176 template <typename NameGetter> CheckMethodArgsSubtypePrimitive(NameGetter & nameGetter,Type & formalType,Type & actualType,int regNum)4177 bool CheckMethodArgsSubtypePrimitive(NameGetter &nameGetter, Type &formalType, Type &actualType, int regNum) 4178 { 4179 // check implicit conversion of primitive types 4180 TypeId formalId = formalType.ToTypeId(); 4181 CheckResult checkResult = CheckResult::ok; 4182 4183 if (!IsSubtype(actualType, primitive_, GetTypeSystem())) { 4184 return false; 4185 } 4186 // !!!!!! NOTE: need to check all possible TypeId-s against formal_id 4187 TypeId actualId = actualType.ToTypeId(); 4188 if (actualId != TypeId::INVALID) { 4189 checkResult = ark::verifier::CheckMethodArgs(formalId, actualId); 4190 } else { 4191 // special case, where type after contexts LUB operation is inexact one, like 4192 // integral32_Type() 4193 if ((IsSubtype(formalType, integral32_, GetTypeSystem()) && 4194 IsSubtype(actualType, integral32_, GetTypeSystem())) || 4195 (IsSubtype(formalType, integral64_, GetTypeSystem()) && 4196 IsSubtype(actualType, integral64_, GetTypeSystem())) || 4197 (IsSubtype(formalType, float64_, GetTypeSystem()) && 4198 IsSubtype(actualType, float64_, GetTypeSystem()))) { 4199 SHOW_MSG(CallFormalActualDifferent) 4200 LOG_VERIFIER_CALL_FORMAL_ACTUAL_DIFFERENT(ToString(formalType), ToString(actualType)); 4201 END_SHOW_MSG(); 4202 } else { 4203 checkResult = ark::verifier::CheckMethodArgs(formalId, actualId); 4204 } 4205 } 4206 if (!checkResult.IsOk()) { 4207 SHOW_MSG(DebugCallParameterTypes) 4208 LogInnerMessage(checkResult); 4209 LOG_VERIFIER_DEBUG_CALL_PARAMETER_TYPES( 4210 nameGetter(), 4211 (regNum == INVALID_REG ? "" : PandaString {"Actual parameter in "} + RegisterName(regNum) + ". "), 4212 ToString(actualType), ToString(formalType)); 4213 END_SHOW_MSG(); 4214 status_ = checkResult.status; 4215 if (status_ == VerificationStatus::ERROR) { 4216 return false; 4217 } 4218 } 4219 4220 return true; 4221 } 4222 4223 template <typename NameGetter> CheckMethodArgsIncompatibleTypes(NameGetter & nameGetter,int regNum,Type & actualType,Type & formalType)4224 bool CheckMethodArgsIncompatibleTypes(NameGetter &nameGetter, int regNum, Type &actualType, Type &formalType) 4225 { 4226 auto const normType = GetTypeSystem()->NormalizedTypeOf(formalType); 4227 Type normActualType = GetTypeSystem()->NormalizedTypeOf(actualType); 4228 4229 PandaString regOrParam = regNum == INVALID_REG ? "Actual parameter" : RegisterName(regNum, true); 4230 SHOW_MSG(BadCallIncompatibleParameter) 4231 LOG_VERIFIER_BAD_CALL_INCOMPATIBLE_PARAMETER(nameGetter(), regOrParam, ToString(normActualType), 4232 ToString(normType)); 4233 END_SHOW_MSG(); 4234 SET_STATUS_FOR_MSG(BadCallIncompatibleParameter, WARNING); 4235 return false; 4236 } 4237 4238 template <typename NameGetter> CheckMethodArgsBot(NameGetter & nameGetter,Type & actualType)4239 bool CheckMethodArgsBot(NameGetter &nameGetter, Type &actualType) 4240 { 4241 if (actualType == Type::Bot()) { 4242 LOG_VERIFIER_CALL_FORMAL_ACTUAL_BOTH_BOT_OR_TOP("Bot"); 4243 return true; 4244 } 4245 4246 SHOW_MSG(BadCallFormalIsBot) 4247 LOG_VERIFIER_BAD_CALL_FORMAL_IS_BOT(nameGetter(), ToString(actualType)); 4248 END_SHOW_MSG(); 4249 SET_STATUS_FOR_MSG(BadCallFormalIsBot, WARNING); 4250 return false; 4251 } 4252 CheckMethodArgsTop(Type & actualType)4253 bool CheckMethodArgsTop(Type &actualType) 4254 { 4255 if (actualType == Type::Top()) { 4256 LOG_VERIFIER_CALL_FORMAL_ACTUAL_BOTH_BOT_OR_TOP("Top"); 4257 return true; 4258 } 4259 SHOW_MSG(CallFormalTop) 4260 LOG_VERIFIER_CALL_FORMAL_TOP(); 4261 END_SHOW_MSG(); 4262 return true; 4263 } 4264 4265 template <typename NameGetter> CheckMethodArgsCheckType(NameGetter & nameGetter,Type & actualType,Type & formalType,int regNum)4266 void CheckMethodArgsCheckType(NameGetter &nameGetter, Type &actualType, Type &formalType, int regNum) 4267 { 4268 if (regNum == INVALID_REG) { 4269 SHOW_MSG(BadCallWrongParameter) 4270 LOG_VERIFIER_BAD_CALL_WRONG_PARAMETER(nameGetter(), ToString(actualType), ToString(formalType)); 4271 END_SHOW_MSG(); 4272 SET_STATUS_FOR_MSG(BadCallWrongParameter, WARNING); 4273 return; 4274 } 4275 SHOW_MSG(BadCallWrongRegister) 4276 LOG_VERIFIER_BAD_CALL_WRONG_REGISTER(nameGetter(), regNum); 4277 END_SHOW_MSG(); 4278 SET_STATUS_FOR_MSG(BadCallWrongRegister, WARNING); 4279 } 4280 4281 template <typename NameGetter> CheckMethodArgsTooFewParmeters(NameGetter & nameGetter)4282 bool CheckMethodArgsTooFewParmeters(NameGetter &nameGetter) 4283 { 4284 SHOW_MSG(BadCallTooFewParameters) 4285 LOG_VERIFIER_BAD_CALL_TOO_FEW_PARAMETERS(nameGetter()); 4286 END_SHOW_MSG(); 4287 SET_STATUS_FOR_MSG(BadCallTooFewParameters, WARNING); 4288 return false; 4289 } 4290 CheckMethodArgsNotFit(Type & formalType,Type & actualType,int regNum,bool & incompatibleTypes)4291 bool CheckMethodArgsNotFit(Type &formalType, Type &actualType, int regNum, bool &incompatibleTypes) 4292 { 4293 auto const normType = GetTypeSystem()->NormalizedTypeOf(formalType); 4294 Type normActualType = GetTypeSystem()->NormalizedTypeOf(actualType); 4295 4296 if (regNum != INVALID_REG && IsSubtype(formalType, refType_, GetTypeSystem()) && formalType != Type::Bot() && 4297 IsSubtype(actualType, refType_, GetTypeSystem())) { 4298 if (IsSubtype(actualType, formalType, GetTypeSystem())) { 4299 return true; 4300 } 4301 if (!config->opts.debug.allow.wrongSubclassingInMethodArgs) { 4302 incompatibleTypes = true; 4303 } 4304 } else if (formalType != Type::Bot() && formalType != Type::Top() && 4305 !IsSubtype(normActualType, normType, GetTypeSystem())) { 4306 incompatibleTypes = true; 4307 } 4308 4309 return false; 4310 } 4311 4312 private: 4313 BytecodeInstructionSafe inst_; 4314 VerificationContext &context_; 4315 VerificationStatus status_ {VerificationStatus::OK}; 4316 // #ifndef NDEBUG 4317 bool debug_ {false}; 4318 uint32_t debugOffset_ {0}; 4319 // #endif 4320 EntryPointType codeType_; 4321 SetStatusAtLeast(VerificationStatus newStatus)4322 void SetStatusAtLeast(VerificationStatus newStatus) 4323 { 4324 status_ = std::max(status_, newStatus); 4325 } 4326 MsgClassToStatus(MethodOption::MsgClass msgClass)4327 static inline VerificationStatus MsgClassToStatus(MethodOption::MsgClass msgClass) 4328 { 4329 switch (msgClass) { 4330 case MethodOption::MsgClass::HIDDEN: 4331 return VerificationStatus::OK; 4332 case MethodOption::MsgClass::WARNING: 4333 return VerificationStatus::WARNING; 4334 case MethodOption::MsgClass::ERROR: 4335 return VerificationStatus::ERROR; 4336 default: 4337 UNREACHABLE(); 4338 } 4339 } 4340 GetFieldName(Field const * field)4341 static PandaString GetFieldName(Field const *field) 4342 { 4343 return PandaString {field->GetClass()->GetName()} + "." + utf::Mutf8AsCString(field->GetName().data); 4344 } 4345 }; 4346 } // namespace ark::verifier 4347 4348 #endif // PANDA_VERIFICATION_ABSINT_ABS_INT_INL_H 4349