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