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