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