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