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