• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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     template <bool IS_LOAD>
CheckFieldAccessByName(int regIdx,Type expectedFieldType)2524     bool CheckFieldAccessByName(int regIdx, [[maybe_unused]] Type expectedFieldType)
2525     {
2526         Field const *rawField = GetCachedField();
2527         Type objType;
2528 
2529         // currently all union type named access sites are encoded as “$NamedAccessMeta” class fields
2530         // at bytecode level, thus we do not have accurate union type info to verify each variables
2531         // so the current temporary solution would be to skip verification for union types.This
2532         // actually introduce insecure possibilities here. Accurate verification for union types
2533         // will need redesign for union types support in the future
2534         //
2535         // based on the above,here we skip:
2536         // 1. checking whether a field existed in the union or not
2537         // 2. skip checking member access violiations
2538         return CheckFieldAccessByNameStartCheck(regIdx, rawField, objType);
2539     }
2540 
2541     template <BytecodeInstructionSafe::Format FORMAT>
ProcessFieldLoadByName(int regSrc,Type expectedFieldType)2542     bool ProcessFieldLoadByName(int regSrc, Type expectedFieldType)
2543     {
2544         if (!CheckFieldAccessByName<true>(regSrc, expectedFieldType)) {
2545             return false;
2546         }
2547         Field const *field = GetCachedField();
2548 
2549         if (field == nullptr) {
2550             SET_STATUS_FOR_MSG(CannotResolveFieldId, OK);
2551             return false;
2552         }
2553 
2554         auto type = GetFieldType();
2555         if (!type.IsConsistent()) {
2556             return false;
2557         }
2558         SetReg(ACC, type);
2559         MoveToNextInst<FORMAT>();
2560         return true;
2561     }
2562 
2563     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsLdobjName()2564     bool HandleEtsLdobjName()
2565     {
2566         LOG_INST();
2567         DBGBRK();
2568         uint16_t vs = inst_.GetVReg<FORMAT>();
2569         Sync();
2570         return ProcessFieldLoadByName<FORMAT>(vs, bits32_);
2571     }
2572 
2573     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsLdobjNameWide()2574     bool HandleEtsLdobjNameWide()
2575     {
2576         LOG_INST();
2577         DBGBRK();
2578         uint16_t vs = inst_.GetVReg<FORMAT>();
2579         Sync();
2580         return ProcessFieldLoadByName<FORMAT>(vs, bits64_);
2581     }
2582 
2583     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsLdobjNameObj()2584     bool HandleEtsLdobjNameObj()
2585     {
2586         LOG_INST();
2587         DBGBRK();
2588         uint16_t vs = inst_.GetVReg<FORMAT>();
2589         Sync();
2590         return ProcessFieldLoadByName<FORMAT>(vs, refType_);
2591     }
2592 
2593     template <BytecodeInstructionSafe::Format FORMAT, typename Check>
ProcessStoreFieldByName(int vd,Type expectedFieldType,Check check)2594     bool ProcessStoreFieldByName(int vd, Type expectedFieldType, Check check)
2595     {
2596         if (!CheckRegType(ACC, expectedFieldType)) {
2597             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
2598             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2599             return false;
2600         }
2601         if (!CheckFieldAccessByName<false>(vd, expectedFieldType)) {
2602             return false;
2603         }
2604 
2605         Field const *field = GetCachedField();
2606 
2607         if (field == nullptr) {
2608             SET_STATUS_FOR_MSG(CannotResolveFieldId, OK);
2609             return false;
2610         }
2611         Type fieldType = GetFieldType();
2612         if (!fieldType.IsConsistent()) {
2613             return false;
2614         }
2615 
2616         Type vsType = GetRegType(ACC);
2617 
2618         CheckResult const &result = check(fieldType.ToTypeId(), vsType.ToTypeId());
2619         if (result.status != VerificationStatus::OK) {
2620             LOG_VERIFIER_DEBUG_STORE_FIELD(GetFieldName(field), ToString(fieldType), ToString(vsType));
2621             status_ = result.status;
2622             if (result.IsError()) {
2623                 return false;
2624             }
2625         }
2626 
2627         MoveToNextInst<FORMAT>();
2628         return true;
2629     }
2630 
2631     template <BytecodeInstructionSafe::Format FORMAT>
ProcessStobjObjByName(int vd)2632     bool ProcessStobjObjByName(int vd)
2633     {
2634         if (!CheckFieldAccessByName<false>(vd, refType_)) {
2635             return false;
2636         }
2637 
2638         Field const *field = GetCachedField();
2639 
2640         if (field == nullptr) {
2641             SET_STATUS_FOR_MSG(CannotResolveFieldId, OK);
2642             return false;
2643         }
2644 
2645         Type fieldType = GetFieldType();
2646         if (!fieldType.IsConsistent()) {
2647             return false;
2648         }
2649 
2650         if (!CheckRegType(ACC, refType_)) {
2651             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
2652             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2653             return false;
2654         }
2655 
2656         Type vsType = GetRegType(ACC);
2657         if (!IsSubtype(vsType, fieldType, GetTypeSystem())) {
2658             SHOW_MSG(BadAccumulatorType)
2659             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE(ToString(vsType), ToString(fieldType));
2660             END_SHOW_MSG();
2661             SET_STATUS_FOR_MSG(BadAccumulatorType, WARNING);
2662             return false;
2663         }
2664 
2665         MoveToNextInst<FORMAT>();
2666         return true;
2667     }
2668 
2669     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsStobjName()2670     bool HandleEtsStobjName()
2671     {
2672         LOG_INST();
2673         DBGBRK();
2674         uint16_t vd = inst_.GetVReg<FORMAT>();
2675         Sync();
2676 
2677         return ProcessStoreFieldByName<FORMAT>(vd, bits32_, CheckStobj);
2678     }
2679 
2680     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsStobjNameWide()2681     bool HandleEtsStobjNameWide()
2682     {
2683         LOG_INST();
2684         DBGBRK();
2685         uint16_t vd = inst_.GetVReg<FORMAT>();
2686         Sync();
2687 
2688         return ProcessStoreFieldByName<FORMAT>(vd, bits64_, CheckStobjWide);
2689     }
2690 
2691     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsStobjNameObj()2692     bool HandleEtsStobjNameObj()
2693     {
2694         LOG_INST();
2695         DBGBRK();
2696         uint16_t vd = inst_.GetVReg<FORMAT>();
2697         Sync();
2698         return ProcessStobjObjByName<FORMAT>(vd);
2699     }
2700 
2701     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsCallNameShort()2702     bool HandleEtsCallNameShort()
2703     {
2704         LOG_INST();
2705         DBGBRK();
2706         // NOTE issue(21892) support callbyname
2707         // This stub should be replaced with appropriate handler
2708         return false;
2709     }
2710 
2711     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsCallName()2712     bool HandleEtsCallName()
2713     {
2714         LOG_INST();
2715         DBGBRK();
2716         // NOTE issue(21892) support callbyname
2717         // This stub should be replaced with appropriate handler
2718         return false;
2719     }
2720 
2721     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsCallNameRange()2722     bool HandleEtsCallNameRange()
2723     {
2724         LOG_INST();
2725         DBGBRK();
2726         // NOTE issue(21892) support callbyname
2727         // This stub should be replaced with appropriate handler
2728         return false;
2729     }
2730 
2731     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsLdnullvalue()2732     bool HandleEtsLdnullvalue()
2733     {
2734         LOG_INST();
2735         DBGBRK();
2736         Sync();
2737         SetAcc(objectType_);
2738         MoveToNextInst<FORMAT>();
2739         return true;
2740     }
2741 
2742     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsMovnullvalue()2743     bool HandleEtsMovnullvalue()
2744     {
2745         LOG_INST();
2746         DBGBRK();
2747         uint16_t vd = inst_.GetVReg<FORMAT>();
2748         Sync();
2749         SetReg(vd, objectType_);
2750         MoveToNextInst<FORMAT>();
2751         return true;
2752     }
2753 
2754     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsIsnullvalue()2755     bool HandleEtsIsnullvalue()
2756     {
2757         LOG_INST();
2758         DBGBRK();
2759         Sync();
2760 
2761         if (!CheckRegType(ACC, refType_)) {
2762             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
2763             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2764             return false;
2765         }
2766         SetAcc(i32_);
2767 
2768         MoveToNextInst<FORMAT>();
2769         return true;
2770     }
2771 
2772     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsEqualityHelper(uint16_t v1,uint16_t v2)2773     bool HandleEtsEqualityHelper(uint16_t v1, uint16_t v2)
2774     {
2775         if (!CheckRegType(v1, refType_)) {
2776             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
2777             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2778             return false;
2779         }
2780         if (!CheckRegType(v2, refType_)) {
2781             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
2782             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2783             return false;
2784         }
2785         SetAcc(i32_);
2786 
2787         MoveToNextInst<FORMAT>();
2788         return true;
2789     }
2790 
2791     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsEquals()2792     bool HandleEtsEquals()
2793     {
2794         LOG_INST();
2795         DBGBRK();
2796         uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>();
2797         uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>();
2798         Sync();
2799 
2800         return HandleEtsEqualityHelper<FORMAT>(v1, v2);
2801     }
2802 
2803     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsStrictequals()2804     bool HandleEtsStrictequals()
2805     {
2806         LOG_INST();
2807         DBGBRK();
2808         uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>();
2809         uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>();
2810         Sync();
2811 
2812         return HandleEtsEqualityHelper<FORMAT>(v1, v2);
2813     }
2814 
2815     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsTypeof()2816     bool HandleEtsTypeof()
2817     {
2818         LOG_INST();
2819         DBGBRK();
2820         uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>();
2821         Sync();
2822 
2823         if (!CheckRegType(v1, refType_)) {
2824             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
2825             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2826             return false;
2827         }
2828         SetAcc(GetTypeSystem()->StringClass());
2829 
2830         MoveToNextInst<FORMAT>();
2831         return true;
2832     }
2833 
2834     template <BytecodeInstructionSafe::Format FORMAT>
HandleEtsIstrue()2835     bool HandleEtsIstrue()
2836     {
2837         LOG_INST();
2838         DBGBRK();
2839         uint16_t v = inst_.GetVReg<FORMAT, 0x00>();
2840         Sync();
2841 
2842         if (!CheckRegType(v, refType_)) {
2843             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
2844             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2845             return false;
2846         }
2847         SetAcc(i32_);
2848 
2849         MoveToNextInst<FORMAT>();
2850         return true;
2851     }
2852 
2853     template <BytecodeInstructionSafe::Format FORMAT>
HandleReturnWide()2854     bool HandleReturnWide()
2855     {
2856         LOG_INST();
2857         DBGBRK();
2858         Sync();
2859 
2860         if (!CheckType(ReturnType(), bits64_)) {
2861             LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE(".64", ToString(ReturnType()), ToString(bits64_));
2862             status_ = VerificationStatus::ERROR;
2863             return false;
2864         }
2865 
2866         if (!IsRegDefined(ACC)) {
2867             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2868             return false;
2869         }
2870 
2871         if (!CheckType(GetAccType(), bits64_)) {
2872             LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE(ToString(GetAccType()));
2873             status_ = VerificationStatus::ERROR;
2874         }
2875         return false;
2876     }
2877 
2878     template <BytecodeInstructionSafe::Format FORMAT>
HandleReturnObj()2879     bool HandleReturnObj()
2880     {
2881         LOG_INST();
2882         DBGBRK();
2883         Sync();
2884 
2885         if (!CheckType(ReturnType(), refType_)) {
2886             LOG_VERIFIER_BAD_RETURN_INSTRUCTION_TYPE(".obj", ToString(ReturnType()), ToString(refType_));
2887             status_ = VerificationStatus::ERROR;
2888             return false;
2889         }
2890 
2891         if (!IsRegDefined(ACC)) {
2892             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
2893             return false;
2894         }
2895 
2896         auto accType = GetAccType();
2897         if (!CheckType(accType, ReturnType())) {
2898             LOG_VERIFIER_BAD_ACCUMULATOR_RETURN_VALUE_TYPE_WITH_SUBTYPE(ToString(accType), ToString(ReturnType()));
2899             // NOTE(vdyadov) : after solving issues with set of types in LUB, uncomment next line
2900             status_ = VerificationStatus::WARNING;
2901         }
2902 
2903         return false;
2904     }
2905 
2906     template <BytecodeInstructionSafe::Format FORMAT>
HandleReturnVoid()2907     bool HandleReturnVoid()
2908     {
2909         LOG_INST();
2910         DBGBRK();
2911         // NOTE(vdyadov): think of introducing void as of separate type, like null
2912         Sync();
2913 
2914         if (ReturnType() != Type::Top()) {
2915             LOG_VERIFIER_BAD_RETURN_VOID_INSTRUCTION_TYPE(ToString(ReturnType()));
2916             status_ = VerificationStatus::ERROR;
2917         }
2918 
2919         return false;
2920     }
2921 
2922     template <BytecodeInstructionSafe::Format FORMAT>
HandleCheckcast()2923     bool HandleCheckcast()
2924     {
2925         LOG_INST();
2926         DBGBRK();
2927         Sync();
2928         Type cachedType = GetCachedType();
2929         if (!CheckCastArrayObjectRegDef(cachedType)) {
2930             return false;
2931         }
2932         auto accType = GetAccType();
2933         // NOTE(vdyadov): remove this check after #2365
2934         if (!CheckCastRefArrayType(accType)) {
2935             return false;
2936         }
2937 
2938         if (IsSubtype(accType, nullRefType_, GetTypeSystem())) {
2939             LOG_VERIFIER_ACCUMULATOR_ALWAYS_NULL();
2940             SET_STATUS_FOR_MSG(AccumulatorAlwaysNull, OK);
2941             // Don't set types for "others of the same origin" when origin is null: n = null, a = n, b = n, a =
2942             // (NewType)x
2943             MoveToNextInst<FORMAT>();
2944             return true;
2945         }
2946 
2947         if (IsSubtype(accType, cachedType, GetTypeSystem())) {
2948             LOG_VERIFIER_REDUNDANT_CHECK_CAST(ToString(accType), ToString(cachedType));
2949             SET_STATUS_FOR_MSG(RedundantCheckCast, OK);
2950             // Do not update register type to parent type as we loose details and can get errors on further flow
2951             MoveToNextInst<FORMAT>();
2952             return true;
2953         }
2954 
2955         if (IsSubtype(cachedType, arrayType_, GetTypeSystem())) {
2956             auto eltType = cachedType.GetArrayElementType(GetTypeSystem());
2957             if (!IsSubtype(accType, arrayType_, GetTypeSystem()) && !IsSubtype(cachedType, accType, GetTypeSystem())) {
2958                 LOG_VERIFIER_IMPOSSIBLE_CHECK_CAST(ToString(accType));
2959                 status_ = VerificationStatus::WARNING;
2960             } else if (IsSubtype(accType, arrayType_, GetTypeSystem())) {
2961                 auto accEltType = accType.GetArrayElementType(GetTypeSystem());
2962                 if (accEltType.IsConsistent() && !IsSubtype(accEltType, eltType, GetTypeSystem()) &&
2963                     !IsSubtype(eltType, accEltType, GetTypeSystem())) {
2964                     LOG_VERIFIER_IMPOSSIBLE_ARRAY_CHECK_CAST(ToString(accEltType));
2965                     SET_STATUS_FOR_MSG(ImpossibleArrayCheckCast, OK);
2966                 }
2967             }
2968         } else if (TpIntersection(cachedType, accType, GetTypeSystem()) == bot_) {
2969             LOG_VERIFIER_INCOMPATIBLE_ACCUMULATOR_TYPE(ToString(accType));
2970             SET_STATUS_FOR_MSG(IncompatibleAccumulatorType, OK);
2971         }
2972 
2973         if (status_ == VerificationStatus::ERROR) {
2974             SetAcc(top_);
2975             return false;
2976         }
2977 
2978         SetAccAndOthersOfSameOrigin(TpIntersection(cachedType, accType, GetTypeSystem()));
2979 
2980         MoveToNextInst<FORMAT>();
2981         return true;
2982     }
2983 
2984     template <BytecodeInstructionSafe::Format FORMAT>
HandleIsinstance()2985     bool HandleIsinstance()
2986     {
2987         LOG_INST();
2988         DBGBRK();
2989         Sync();
2990         Type cachedType = GetCachedType();
2991         if (!CheckInstanceConsistentArrayObjectRegDef(cachedType)) {
2992             return false;
2993         }
2994 
2995         auto *plugin = job_->JobPlugin();
2996         auto const *jobMethod = job_->JobMethod();
2997 
2998         if (!CheckInstanceClass(cachedType, plugin, jobMethod)) {
2999             return false;
3000         }
3001 
3002         auto accType = GetAccType();
3003         // NOTE(vdyadov): remove this check after #2365
3004         if (!IsSubtype(accType, refType_, GetTypeSystem()) && !IsSubtype(accType, arrayType_, GetTypeSystem())) {
3005             LOG_VERIFIER_NON_OBJECT_ACCUMULATOR_TYPE();
3006             status_ = VerificationStatus::ERROR;
3007             return false;
3008         }
3009 
3010         if (IsSubtype(accType, nullRefType_, GetTypeSystem())) {
3011             LOG_VERIFIER_ACCUMULATOR_ALWAYS_NULL();
3012             SET_STATUS_FOR_MSG(AccumulatorAlwaysNull, OK);
3013         } else if (IsSubtype(accType, cachedType, GetTypeSystem())) {
3014             LOG_VERIFIER_REDUNDANT_IS_INSTANCE(ToString(accType), ToString(cachedType));
3015             SET_STATUS_FOR_MSG(RedundantIsInstance, OK);
3016         } else if (IsSubtype(cachedType, arrayType_, GetTypeSystem())) {
3017             auto eltType = cachedType.GetArrayElementType(GetTypeSystem());
3018             auto accEltType = accType.GetArrayElementType(GetTypeSystem());
3019             bool accEltTypeIsEmpty = accEltType.IsConsistent();
3020             if (!IsSubtype(accEltType, eltType, GetTypeSystem()) && !IsSubtype(eltType, accEltType, GetTypeSystem())) {
3021                 if (accEltTypeIsEmpty) {
3022                     LOG_VERIFIER_IMPOSSIBLE_IS_INSTANCE(ToString(accType));
3023                     SET_STATUS_FOR_MSG(ImpossibleIsInstance, OK);
3024                 } else {
3025                     LOG_VERIFIER_IMPOSSIBLE_ARRAY_IS_INSTANCE(ToString(accEltType));
3026                     SET_STATUS_FOR_MSG(ImpossibleArrayIsInstance, OK);
3027                 }
3028             }
3029         } else if (TpIntersection(cachedType, accType, GetTypeSystem()) == bot_) {
3030             LOG_VERIFIER_IMPOSSIBLE_IS_INSTANCE(ToString(accType));
3031             SET_STATUS_FOR_MSG(ImpossibleIsInstance, OK);
3032         }  // else {
3033         // NOTE(vdyadov): here we may increase precision to concrete values in some cases
3034         SetAcc(i32_);
3035         MoveToNextInst<FORMAT>();
3036         return true;
3037     }
3038 
3039     template <typename NameGetter>
3040     bool CheckMethodArgs(NameGetter nameGetter, Method const *method, Span<int> regs, Type constructedType = Type {})
3041     {
3042         auto const &formalArgs = GetTypeSystem()->GetMethodSignature(method)->args;
3043         if (formalArgs.empty()) {
3044             return true;
3045         }
3046 
3047         size_t regsNeeded = !constructedType.IsNone() ? formalArgs.size() - 1 : formalArgs.size();
3048         if (regs.size() < regsNeeded) {
3049             return CheckMethodArgsTooFewParmeters<NameGetter>(nameGetter);
3050         }
3051         auto sigIter = formalArgs.cbegin();
3052         auto regsIter = regs.cbegin();
3053         for (size_t argnum = 0; argnum < formalArgs.size(); argnum++) {
3054             auto regNum = (!constructedType.IsNone() && sigIter == formalArgs.cbegin()) ? INVALID_REG : *(regsIter++);
3055             auto formalType = *(sigIter++);
3056 
3057             if (regNum != INVALID_REG && !IsRegDefined(regNum)) {
3058                 LOG_VERIFIER_BAD_CALL_UNDEFINED_REGISTER(nameGetter(), regNum);
3059                 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3060                 return false;
3061             }
3062             Type actualType = regNum == INVALID_REG ? constructedType : GetRegType(regNum);
3063             // arg: NormalizedTypeOf(actual_type) <= norm_type
3064             // check of physical compatibility
3065             bool incompatibleTypes = false;
3066             if (CheckMethodArgsNotFit(formalType, actualType, regNum, incompatibleTypes)) {
3067                 continue;
3068             }
3069             if (incompatibleTypes) {
3070                 return CheckMethodArgsIncompatibleTypes<NameGetter>(nameGetter, regNum, actualType, formalType);
3071             }
3072             if (formalType == Type::Bot()) {
3073                 return CheckMethodArgsBot<NameGetter>(nameGetter, actualType);
3074             }
3075             if (formalType == Type::Top()) {
3076                 return CheckMethodArgsTop(actualType);
3077             }
3078             if (IsSubtype(formalType, primitive_, GetTypeSystem())) {
3079                 if (!CheckMethodArgsSubtypePrimitive(nameGetter, formalType, actualType, regNum)) {
3080                     return false;
3081                 }
3082                 continue;
3083             }
3084             if (!CheckType(actualType, formalType)) {
3085                 CheckMethodArgsCheckType<NameGetter>(nameGetter, actualType, formalType, regNum);
3086                 if (!config->opts.debug.allow.wrongSubclassingInMethodArgs) {
3087                     status_ = VerificationStatus::ERROR;
3088                     return false;
3089                 }
3090             }
3091         }
3092         return true;
3093     }
3094 
3095     template <BytecodeInstructionSafe::Format FORMAT>
CheckCall(Method const * method,Span<int> regs)3096     bool CheckCall(Method const *method, Span<int> regs)
3097     {
3098         if (method == nullptr) {
3099             SET_STATUS_FOR_MSG(CannotResolveMethodId, OK);
3100             return false;
3101         }
3102 
3103         auto *plugin = job_->JobPlugin();
3104         auto const *jobMethod = job_->JobMethod();
3105         auto result = plugin->CheckMethodAccessViolation(method, jobMethod, GetTypeSystem());
3106         if (!result.IsOk()) {
3107             const auto &verifOpts = config->opts;
3108             if (verifOpts.debug.allow.methodAccessViolation && result.IsError()) {
3109                 result.status = VerificationStatus::WARNING;
3110             }
3111             LogInnerMessage(result);
3112             LOG_VERIFIER_DEBUG_CALL_FROM_TO(job_->JobMethod()->GetFullName(), method->GetFullName());
3113             status_ = result.status;
3114             if (status_ == VerificationStatus::ERROR) {
3115                 return false;
3116             }
3117         }
3118 
3119         const auto *methodSig = GetTypeSystem()->GetMethodSignature(method);
3120         auto methodNameGetter = [method]() { return method->GetFullName(); };
3121         Type resultType = methodSig->result;
3122 
3123         if (!debugCtx->SkipVerificationOfCall(method->GetUniqId()) &&
3124             !CheckMethodArgs(methodNameGetter, method, regs)) {
3125             return false;
3126         }
3127         SetAcc(resultType);
3128         MoveToNextInst<FORMAT>();
3129         return true;
3130     }
3131 
3132     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallShort()3133     bool HandleCallShort()
3134     {
3135         LOG_INST();
3136         DBGBRK();
3137         uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>();
3138         uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>();
3139         Method const *method = GetCachedMethod();
3140         if (method != nullptr) {
3141             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3142         }
3143 
3144         if (method != nullptr && method->IsAbstract()) {
3145             LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName());
3146             SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING);
3147             return false;
3148         }
3149 
3150         Sync();
3151         std::array<int, 2UL> regs {vs1, vs2};
3152         return CheckCall<FORMAT>(method, Span {regs});
3153     }
3154 
3155     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallAccShort()3156     bool HandleCallAccShort()
3157     {
3158         LOG_INST();
3159         DBGBRK();
3160         uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>();
3161         auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x00>());
3162         static constexpr auto NUM_ARGS = 2;
3163         if (accPos >= NUM_ARGS) {
3164             LOG_VERIFIER_ACCUMULATOR_POSITION_IS_OUT_OF_RANGE();
3165             SET_STATUS_FOR_MSG(AccumulatorPositionIsOutOfRange, WARNING);
3166             return status_ != VerificationStatus::ERROR;
3167         }
3168         Method const *method = GetCachedMethod();
3169         if (method != nullptr) {
3170             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3171         }
3172 
3173         if (method != nullptr && method->IsAbstract()) {
3174             LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName());
3175             SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING);
3176             return false;
3177         }
3178 
3179         Sync();
3180         std::array<int, NUM_ARGS> regs {};
3181         if (accPos == 0) {
3182             regs = {ACC, vs1};
3183         } else {
3184             regs = {vs1, ACC};
3185         }
3186         return CheckCall<FORMAT>(method, Span {regs});
3187     }
3188 
3189     template <BytecodeInstructionSafe::Format FORMAT>
3190     bool HandleCalliDynShort();
3191 
3192     template <BytecodeInstructionSafe::Format FORMAT>
3193     bool HandleCalliDyn();
3194 
3195     template <BytecodeInstructionSafe::Format FORMAT>
3196     bool HandleCalliDynRange();
3197 
3198     template <BytecodeInstructionSafe::Format FORMAT>
HandleCall()3199     bool HandleCall()
3200     {
3201         LOG_INST();
3202         DBGBRK();
3203         uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>();
3204         uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>();
3205         uint16_t vs3 = inst_.GetVReg<FORMAT, 0x02>();
3206         uint16_t vs4 = inst_.GetVReg<FORMAT, 0x03>();
3207         Method const *method = GetCachedMethod();
3208         if (method != nullptr) {
3209             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3210         }
3211 
3212         if (method != nullptr && method->IsAbstract()) {
3213             LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName());
3214             SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING);
3215             return false;
3216         }
3217 
3218         Sync();
3219         std::array<int, 4UL> regs {vs1, vs2, vs3, vs4};
3220         return CheckCall<FORMAT>(method, Span {regs});
3221     }
3222 
3223     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallAcc()3224     bool HandleCallAcc()
3225     {
3226         LOG_INST();
3227         DBGBRK();
3228         auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x0>());
3229         static constexpr auto NUM_ARGS = 4;
3230         if (accPos >= NUM_ARGS) {
3231             LOG_VERIFIER_ACCUMULATOR_POSITION_IS_OUT_OF_RANGE();
3232             SET_STATUS_FOR_MSG(AccumulatorPositionIsOutOfRange, WARNING);
3233             return status_ != VerificationStatus::ERROR;
3234         }
3235         Method const *method = GetCachedMethod();
3236         if (method != nullptr) {
3237             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3238         }
3239 
3240         if (method != nullptr && method->IsAbstract()) {
3241             LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName());
3242             SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING);
3243             return false;
3244         }
3245 
3246         Sync();
3247         std::array<int, NUM_ARGS> regs {};
3248         auto regIdx = 0;
3249         for (unsigned i = 0; i < NUM_ARGS; ++i) {
3250             if (i == accPos) {
3251                 regs[i] = ACC;
3252             } else {
3253                 regs[i] = static_cast<int>(inst_.GetVReg(regIdx++));
3254             }
3255         }
3256         return CheckCall<FORMAT>(method, Span {regs});
3257     }
3258 
3259     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallRange()3260     bool HandleCallRange()
3261     {
3262         LOG_INST();
3263         DBGBRK();
3264         uint16_t vs = inst_.GetVReg<FORMAT, 0x00>();
3265         Method const *method = GetCachedMethod();
3266         if (method != nullptr) {
3267             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3268         }
3269 
3270         if (method != nullptr && method->IsAbstract()) {
3271             LOG_VERIFIER_BAD_CALL_STATICALLY_ABSTRACT_METHOD(method->GetFullName());
3272             SET_STATUS_FOR_MSG(BadCallStaticallyAbstractMethod, WARNING);
3273             return false;
3274         }
3275 
3276         Sync();
3277         std::vector<int> regs;
3278         for (auto regIdx = vs; ExecCtx().CurrentRegContext().IsRegDefined(regIdx); regIdx++) {
3279             regs.push_back(regIdx);
3280         }
3281         return CheckCall<FORMAT>(method, Span {regs});
3282     }
3283 
3284     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallVirtShort()3285     bool HandleCallVirtShort()
3286     {
3287         LOG_INST();
3288         DBGBRK();
3289         uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>();
3290         uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>();
3291         Method const *method = GetCachedMethod();
3292         if (method != nullptr) {
3293             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3294         }
3295         if (method != nullptr && method->IsStatic()) {
3296             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName());
3297             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING);
3298             return false;
3299         }
3300 
3301         Sync();
3302         std::array<int, 2UL> regs {vs1, vs2};
3303         return CheckCall<FORMAT>(method, Span {regs});
3304     }
3305 
3306     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallVirtAccShort()3307     bool HandleCallVirtAccShort()
3308     {
3309         LOG_INST();
3310         DBGBRK();
3311         uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>();
3312         auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x00>());
3313         static constexpr auto NUM_ARGS = 2;
3314         Method const *method = GetCachedMethod();
3315         if (method != nullptr) {
3316             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3317         }
3318         if (method != nullptr && method->IsStatic()) {
3319             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName());
3320             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING);
3321             return false;
3322         }
3323         Sync();
3324         std::array<int, NUM_ARGS> regs {};
3325         if (accPos == 0) {
3326             regs = {ACC, vs1};
3327         } else {
3328             regs = {vs1, ACC};
3329         }
3330         return CheckCall<FORMAT>(method, Span {regs});
3331     }
3332 
3333     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallVirt()3334     bool HandleCallVirt()
3335     {
3336         LOG_INST();
3337         DBGBRK();
3338         uint16_t vs1 = inst_.GetVReg<FORMAT, 0x00>();
3339         uint16_t vs2 = inst_.GetVReg<FORMAT, 0x01>();
3340         uint16_t vs3 = inst_.GetVReg<FORMAT, 0x02>();
3341         uint16_t vs4 = inst_.GetVReg<FORMAT, 0x03>();
3342         Method const *method = GetCachedMethod();
3343         if (method != nullptr) {
3344             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3345         }
3346         if (method != nullptr && method->IsStatic()) {
3347             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName());
3348             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING);
3349             return false;
3350         }
3351 
3352         Sync();
3353         std::array<int, 4UL> regs {vs1, vs2, vs3, vs4};
3354         return CheckCall<FORMAT>(method, Span {regs});
3355     }
3356 
3357     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallVirtAcc()3358     bool HandleCallVirtAcc()
3359     {
3360         LOG_INST();
3361         DBGBRK();
3362         auto accPos = static_cast<unsigned>(inst_.GetImm<FORMAT, 0x0>());
3363         static constexpr auto NUM_ARGS = 4;
3364         Method const *method = GetCachedMethod();
3365         if (method != nullptr) {
3366             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3367         }
3368         if (method != nullptr && method->IsStatic()) {
3369             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName());
3370             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING);
3371             return false;
3372         }
3373         Sync();
3374         std::array<int, NUM_ARGS> regs {};
3375         auto regIdx = 0;
3376         for (unsigned i = 0; i < NUM_ARGS; ++i) {
3377             if (i == accPos) {
3378                 regs[i] = ACC;
3379             } else {
3380                 regs[i] = static_cast<int>(inst_.GetVReg(regIdx++));
3381             }
3382         }
3383         return CheckCall<FORMAT>(method, Span {regs});
3384     }
3385 
3386     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallVirtRange()3387     bool HandleCallVirtRange()
3388     {
3389         LOG_INST();
3390         DBGBRK();
3391         uint16_t vs = inst_.GetVReg<FORMAT, 0x00>();
3392 
3393         Method const *method = GetCachedMethod();
3394         if (method != nullptr) {
3395             LOG_VERIFIER_DEBUG_METHOD(method->GetFullName());
3396         }
3397         if (method != nullptr && method->IsStatic()) {
3398             LOG_VERIFIER_BAD_CALL_STATIC_METHOD_AS_VIRTUAL(method->GetFullName());
3399             SET_STATUS_FOR_MSG(BadCallStaticMethodAsVirtual, WARNING);
3400             return false;
3401         }
3402 
3403         Sync();
3404         std::vector<int> regs;
3405         for (auto regIdx = vs; ExecCtx().CurrentRegContext().IsRegDefined(regIdx); regIdx++) {
3406             regs.push_back(regIdx);
3407         }
3408         return CheckCall<FORMAT>(method, Span {regs});
3409     }
3410 
3411     template <BytecodeInstructionSafe::Format FORMAT>
HandleThrow()3412     bool HandleThrow()
3413     {
3414         LOG_INST();
3415         DBGBRK();
3416         ExecCtx().SetCheckPoint(inst_.GetAddress());
3417         Sync();
3418         uint16_t vs = inst_.GetVReg<FORMAT>();
3419         if (!CheckRegType(vs, GetTypeSystem()->Throwable())) {
3420             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3421             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3422             return false;
3423         }
3424         // possible implementation:
3425         // on stage of building checkpoints:
3426         // - add all catch block starts as checkpoints/entries
3427         // on absint stage:
3428         // - find corresponding catch block/checkpoint/entry
3429         // - add context to checkpoint/entry
3430         // - add entry to entry list
3431         // - stop absint
3432         return false;
3433     }
3434 
3435     template <BytecodeInstructionSafe::Format FORMAT>
HandleMonitorenter()3436     bool HandleMonitorenter()
3437     {
3438         LOG_INST();
3439         DBGBRK();
3440         Sync();
3441         Type accType = GetAccType();
3442         if (accType == nullRefType_) {
3443             // NOTE(vdyadov): redesign next code, after support exception handlers,
3444             //                treat it as always throw NPE
3445             SHOW_MSG(AlwaysNpeAccumulator)
3446             LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR();
3447             END_SHOW_MSG();
3448             SET_STATUS_FOR_MSG(AlwaysNpeAccumulator, OK);
3449             return false;
3450         }
3451         if (!CheckType(accType, refType_)) {
3452             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3453             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3454             return false;
3455         }
3456         MoveToNextInst<FORMAT>();
3457         return true;
3458     }
3459 
3460     template <BytecodeInstructionSafe::Format FORMAT>
HandleMonitorexit()3461     bool HandleMonitorexit()
3462     {
3463         LOG_INST();
3464         DBGBRK();
3465         Sync();
3466         Type accType = GetAccType();
3467         if (accType == nullRefType_) {
3468             // NOTE(vdyadov): redesign next code, after support exception handlers,
3469             //                treat it as always throw NPE
3470             SHOW_MSG(AlwaysNpeAccumulator)
3471             LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR();
3472             END_SHOW_MSG();
3473             SET_STATUS_FOR_MSG(AlwaysNpeAccumulator, OK);
3474             return false;
3475         }
3476         if (!CheckType(accType, refType_)) {
3477             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3478             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3479             return false;
3480         }
3481         MoveToNextInst<FORMAT>();
3482         return true;
3483     }
3484 
GetInst()3485     BytecodeInstructionSafe GetInst()
3486     {
3487         return inst_;
3488     }
3489 
3490     template <BytecodeInstructionSafe::Format FORMAT>
HandleCallspecRange()3491     bool HandleCallspecRange()
3492     {
3493         // CallspecRange has the same semantics as CallRange in terms of
3494         // input and output for verification
3495         return HandleCallRange<FORMAT>();
3496     }
3497 
3498     static PandaString RegisterName(int regIdx, bool capitalize = false)
3499     {
3500         if (regIdx == ACC) {
3501             return capitalize ? "Accumulator" : "accumulator";
3502         }
3503         return PandaString {capitalize ? "Register v" : "register v"} + NumToStr(regIdx);
3504     }
3505 
3506 private:
GetCachedType()3507     Type GetCachedType() const
3508     {
3509         auto offset = inst_.GetOffset();
3510         if (!job_->IsTypePresentForOffset(offset)) {
3511             SHOW_MSG(CacheMissForClassAtOffset)
3512             LOG_VERIFIER_CACHE_MISS_FOR_CLASS_AT_OFFSET(offset);
3513             END_SHOW_MSG();
3514 
3515             SHOW_MSG(CannotResolveClassId)
3516             LOG_VERIFIER_CANNOT_RESOLVE_CLASS_ID(inst_.GetId().AsFileId().GetOffset());
3517             END_SHOW_MSG();
3518             return Type {};
3519         }
3520         return job_->GetCachedType(offset);
3521     }
3522 
GetCachedMethod()3523     Method const *GetCachedMethod() const
3524     {
3525         auto offset = inst_.GetOffset();
3526         if (!job_->IsMethodPresentForOffset(offset)) {
3527             SHOW_MSG(CacheMissForMethodAtOffset)
3528             LOG_VERIFIER_CACHE_MISS_FOR_METHOD_AT_OFFSET(offset);
3529             END_SHOW_MSG();
3530 
3531             SHOW_MSG(CannotResolveMethodId)
3532             LOG_VERIFIER_CANNOT_RESOLVE_METHOD_ID(inst_.GetId().AsFileId().GetOffset());
3533             END_SHOW_MSG();
3534             return nullptr;
3535         }
3536         return job_->GetCachedMethod(offset);
3537     }
3538 
GetCachedField()3539     Field const *GetCachedField() const
3540     {
3541         auto offset = inst_.GetOffset();
3542         if (!job_->IsFieldPresentForOffset(offset)) {
3543             SHOW_MSG(CacheMissForFieldAtOffset)
3544             LOG_VERIFIER_CACHE_MISS_FOR_FIELD_AT_OFFSET(offset);
3545             END_SHOW_MSG();
3546 
3547             SHOW_MSG(CannotResolveFieldId)
3548             LOG_VERIFIER_CANNOT_RESOLVE_FIELD_ID(inst_.GetId().AsFileId().GetOffset());
3549             END_SHOW_MSG();
3550             return nullptr;
3551         }
3552         return job_->GetCachedField(offset);
3553     }
3554 
3555     template <BytecodeInstructionSafe::Format FORMAT>
MoveToNextInst()3556     void MoveToNextInst()
3557     {
3558         inst_ = inst_.GetNext<FORMAT>();
3559     }
3560 
3561     template <BytecodeInstructionSafe::Format FORMAT>
CheckArrayStore(int v1,int v2,Type expectedEltType)3562     bool CheckArrayStore(int v1, int v2, Type expectedEltType)
3563     {
3564         /*
3565         main rules:
3566         1. instruction should be strict in array element size, so for primitive types type equality is used
3567         2. accumulator may be subtype of array element type (under question)
3568         */
3569         if (!CheckRegType(v2, integral32_)) {
3570             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3571             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3572             return false;
3573         }
3574         if (!CheckRegType(v1, arrayType_)) {
3575             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3576             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3577             return false;
3578         }
3579         if (!IsRegDefined(ACC)) {
3580             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3581             return false;
3582         }
3583         Type regType = GetRegType(v1);
3584         if (regType == nullRefType_) {
3585             // NOTE(vdyadov): redesign next code, after support exception handlers,
3586             //                treat it as always throw NPE
3587             SHOW_MSG(AlwaysNpe)
3588             LOG_VERIFIER_ALWAYS_NPE(v1);
3589             END_SHOW_MSG();
3590             SetAcc(top_);
3591             SET_STATUS_FOR_MSG(AlwaysNpe, OK);
3592             return false;
3593         }
3594 
3595         auto arrEltType = regType.GetArrayElementType(GetTypeSystem());
3596         if (!IsSubtype(arrEltType, expectedEltType, GetTypeSystem())) {
3597             SHOW_MSG(BadArrayElementType2)
3598             LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE2(ToString(arrEltType), ToString(expectedEltType));
3599             END_SHOW_MSG();
3600             SET_STATUS_FOR_MSG(BadArrayElementType2, WARNING);
3601             return false;
3602         }
3603 
3604         Type accType = GetAccType();
3605 
3606         // NOTE(dvyadov): think of subtyping here. Can we really write more precise type into array?
3607         // since there is no problems with storage (all refs are of the same size)
3608         // and no problems with information losses, it seems fine at first sight.
3609         bool res = !IsSubtype(accType, arrEltType, GetTypeSystem());
3610         if (res) {
3611             // accumulator is of wrong type
3612             SHOW_MSG(BadAccumulatorType)
3613             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE(ToString(accType), ToString(arrEltType));
3614             END_SHOW_MSG();
3615             SET_STATUS_FOR_MSG(BadAccumulatorType, WARNING);
3616             return false;
3617         }
3618 
3619         MoveToNextInst<FORMAT>();
3620         return true;
3621     }
3622 
3623     template <BytecodeInstructionSafe::Format FORMAT>
CheckArrayStoreExact(int v1,int v2,Type accSupertype,std::initializer_list<Type> const & expectedEltTypes)3624     bool CheckArrayStoreExact(int v1, int v2, Type accSupertype, std::initializer_list<Type> const &expectedEltTypes)
3625     {
3626         if (!CheckRegType(v2, integral32_) || !CheckRegType(v1, arrayType_) || !IsRegDefined(ACC)) {
3627             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3628             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3629             return false;
3630         }
3631         Type regType = GetRegType(v1);
3632         if (regType == nullRefType_) {
3633             SHOW_MSG(AlwaysNpe)
3634             LOG_VERIFIER_ALWAYS_NPE(v1);
3635             END_SHOW_MSG();
3636             SetAcc(top_);
3637             SET_STATUS_FOR_MSG(AlwaysNpe, OK);
3638             return false;
3639         }
3640 
3641         auto arrEltType = regType.GetArrayElementType(GetTypeSystem());
3642 
3643         auto find = [&expectedEltTypes](auto type) {
3644             // CC-OFFNXT(G.FMT.12) false positive
3645             return std::find(expectedEltTypes.begin(), expectedEltTypes.end(), type) != expectedEltTypes.end();
3646         };
3647         if (!find(arrEltType)) {
3648             // array elt type is not expected one
3649             PandaVector<Type> expectedTypesVec;
3650             for (auto et : expectedEltTypes) {
3651                 expectedTypesVec.push_back(et);
3652             }
3653             LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE3(ToString(arrEltType), ToString(expectedTypesVec));
3654             SET_STATUS_FOR_MSG(BadArrayElementType, WARNING);
3655             return false;
3656         }
3657 
3658         Type accType = GetAccType();
3659         if (!IsSubtype(accType, accSupertype, GetTypeSystem())) {
3660             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE2(ToString(accType));
3661             SET_STATUS_FOR_MSG(BadArrayElementType, WARNING);
3662             return false;
3663         }
3664 
3665         if (!find(accType)) {
3666             // array elt type is not expected one
3667             PandaVector<Type> expectedTypesVec;
3668             expectedTypesVec.insert(expectedTypesVec.end(), expectedEltTypes.begin(), expectedEltTypes.end());
3669             LOG_VERIFIER_BAD_ACCUMULATOR_TYPE3(ToString(accType), ToString(expectedTypesVec));
3670             if (status_ != VerificationStatus::ERROR) {
3671                 status_ = VerificationStatus::WARNING;
3672             }
3673         }
3674 
3675         MoveToNextInst<FORMAT>();
3676         return true;
3677     }
3678 
3679     template <BytecodeInstructionSafe::Format FORMAT, bool REG_DST = false>
CheckBinaryOp2(Type accIn,Type regIn,Type out)3680     bool CheckBinaryOp2(Type accIn, Type regIn, Type out)
3681     {
3682         uint16_t vs;
3683         if constexpr (REG_DST) {
3684             vs = inst_.GetVReg<FORMAT, 0x01>();
3685         } else {
3686             vs = inst_.GetVReg<FORMAT>();
3687         }
3688         if (!CheckRegType(ACC, accIn)) {
3689             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3690             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3691             return false;
3692         }
3693         if (!CheckRegType(vs, regIn)) {
3694             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3695             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3696             return false;
3697         }
3698         if constexpr (REG_DST) {
3699             SetReg(inst_.GetVReg<FORMAT, 0x00>(), out);
3700         } else {
3701             SetAcc(out);
3702         }
3703         MoveToNextInst<FORMAT>();
3704         return true;
3705     }
3706 
3707     template <BytecodeInstructionSafe::Format FORMAT, bool REG_DST = false>
CheckBinaryOp2(Type accIn,Type regIn)3708     bool CheckBinaryOp2(Type accIn, Type regIn)
3709     {
3710         if (!IsRegDefined(ACC)) {
3711             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3712             return false;
3713         }
3714         return CheckBinaryOp2<FORMAT, REG_DST>(accIn, regIn, GetAccType());
3715     }
3716 
3717     template <BytecodeInstructionSafe::Format FORMAT>
CheckBinaryOpImm(Type in,Type out)3718     bool CheckBinaryOpImm(Type in, Type out)
3719     {
3720         uint16_t vd = inst_.GetVReg<FORMAT, 0x00>();
3721         uint16_t vs = inst_.GetVReg<FORMAT, 0x01>();
3722         if (!CheckRegType(vs, in)) {
3723             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3724             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3725             return false;
3726         }
3727         SetReg(vd, out);
3728         MoveToNextInst<FORMAT>();
3729         return true;
3730     }
3731 
3732     template <BytecodeInstructionSafe::Format FORMAT>
CheckBinaryOp2Imm(Type accIn,Type accOut)3733     bool CheckBinaryOp2Imm(Type accIn, Type accOut)
3734     {
3735         if (!CheckRegType(ACC, accIn)) {
3736             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3737             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3738             return false;
3739         }
3740         SetAcc(accOut);
3741         MoveToNextInst<FORMAT>();
3742         return true;
3743     }
3744 
3745     template <BytecodeInstructionSafe::Format FORMAT>
CheckBinaryOp2Imm(Type accIn)3746     bool CheckBinaryOp2Imm(Type accIn)
3747     {
3748         if (!IsRegDefined(ACC)) {
3749             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3750             return false;
3751         }
3752         return CheckBinaryOp2Imm<FORMAT>(accIn, GetAccType());
3753     }
3754 
3755     template <BytecodeInstructionSafe::Format FORMAT>
CheckUnaryOp(Type accIn,Type accOut)3756     bool CheckUnaryOp(Type accIn, Type accOut)
3757     {
3758         if (!CheckRegType(ACC, accIn)) {
3759             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3760             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3761             return false;
3762         }
3763         SetAcc(accOut);
3764         MoveToNextInst<FORMAT>();
3765         return true;
3766     }
3767 
3768     template <BytecodeInstructionSafe::Format FORMAT>
CheckUnaryOp(Type accIn)3769     bool CheckUnaryOp(Type accIn)
3770     {
3771         if (!IsRegDefined(ACC)) {
3772             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3773             return false;
3774         }
3775         return CheckUnaryOp<FORMAT>(accIn, GetAccType());
3776     }
3777 
3778     template <BytecodeInstructionSafe::Format FORMAT, bool REG_DST = false>
CheckBinaryOp(Type v1In,Type v2In,Type out)3779     bool CheckBinaryOp(Type v1In, Type v2In, Type out)
3780     {
3781         uint16_t v1 = inst_.GetVReg<FORMAT, 0x00>();
3782         uint16_t v2 = inst_.GetVReg<FORMAT, 0x01>();
3783         if (!CheckRegType(v1, v1In)) {
3784             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3785             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3786             return false;
3787         }
3788         if (!CheckRegType(v2, v2In)) {
3789             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3790             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3791             return false;
3792         }
3793         if constexpr (REG_DST) {
3794             SetReg(v1, out);
3795         } else {
3796             SetAcc(out);
3797         }
3798         MoveToNextInst<FORMAT>();
3799         return true;
3800     }
3801 
3802     template <BytecodeInstructionSafe::Format FORMAT>
CheckBinaryOp(Type vs1In,Type vs2In)3803     bool CheckBinaryOp(Type vs1In, Type vs2In)
3804     {
3805         if (!IsRegDefined(ACC)) {
3806             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3807             return false;
3808         }
3809         return CheckBinaryOp<FORMAT>(vs1In, vs2In, GetAccType());
3810     }
3811 
3812     template <BytecodeInstructionSafe::Format FORMAT>
HandleConversion(Type from,Type to)3813     bool HandleConversion(Type from, Type to)
3814     {
3815         if (!CheckRegType(ACC, from)) {
3816             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3817             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3818             return false;
3819         }
3820         SetAcc(to);
3821         MoveToNextInst<FORMAT>();
3822         return true;
3823     }
3824 
IsConcreteArrayType(Type type)3825     bool IsConcreteArrayType(Type type)
3826     {
3827         return IsSubtype(type, arrayType_, GetTypeSystem()) && type != arrayType_;
3828     }
3829 
3830     template <BytecodeInstructionSafe::Format FORMAT>
CheckArrayLoad(int vs,std::initializer_list<Type> const & expectedEltTypes)3831     bool CheckArrayLoad(int vs, std::initializer_list<Type> const &expectedEltTypes)
3832     {
3833         if (!CheckRegType(ACC, integral32_)) {
3834             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3835             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3836             return false;
3837         }
3838         if (!CheckRegType(vs, arrayType_)) {
3839             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3840             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3841             return false;
3842         }
3843 
3844         Type regType = GetRegType(vs);
3845         if (regType == nullRefType_) {
3846             // NOTE(vdyadov): redesign next code, after support exception handlers,
3847             //                treat it as always throw NPE
3848             SHOW_MSG(AlwaysNpe)
3849             LOG_VERIFIER_ALWAYS_NPE(vs);
3850             END_SHOW_MSG();
3851             SetAcc(top_);
3852             SET_STATUS_FOR_MSG(AlwaysNpe, OK);
3853             return false;
3854         }
3855         auto &&arrEltType = regType.GetArrayElementType(GetTypeSystem());
3856         auto find = [&expectedEltTypes](auto type) {
3857             for (Type t : expectedEltTypes) {
3858                 if (type == t) {
3859                     return true;
3860                 }
3861             }
3862             return false;
3863         };
3864         auto res = find(arrEltType);
3865         if (!res) {
3866             PandaVector<Type> expectedTypesVec;
3867             for (auto et : expectedEltTypes) {
3868                 expectedTypesVec.push_back(et);
3869             }
3870             LOG_VERIFIER_BAD_ARRAY_ELEMENT_TYPE3(ToString(arrEltType), ToString(expectedTypesVec));
3871             SET_STATUS_FOR_MSG(BadArrayElementType, WARNING);
3872             return false;
3873         }
3874         SetAcc(arrEltType);
3875         MoveToNextInst<FORMAT>();
3876         return true;
3877     }
3878 
ProcessBranching(int32_t offset)3879     bool ProcessBranching(int32_t offset)
3880     {
3881         auto newInst = inst_.JumpTo(offset);
3882         const uint8_t *target = newInst.GetAddress();
3883         if (!context_.CflowInfo().IsAddrValid(target) ||
3884             !context_.CflowInfo().IsFlagSet(target, CflowMethodInfo::INSTRUCTION)) {
3885             LOG_VERIFIER_INCORRECT_JUMP();
3886             status_ = VerificationStatus::ERROR;
3887             return false;
3888         }
3889 
3890 #ifndef NDEBUG
3891         ExecCtx().ProcessJump(
3892             inst_.GetAddress(), target,
3893             [this, printHdr = true](int regIdx, const auto &srcReg, const auto &dstReg) mutable {
3894                 if (printHdr) {
3895                     LOG_VERIFIER_REGISTER_CONFLICT_HEADER();
3896                     printHdr = false;
3897                 }
3898                 LOG_VERIFIER_REGISTER_CONFLICT(RegisterName(regIdx), ToString(srcReg.GetAbstractType()),
3899                                                ToString(dstReg.GetAbstractType()));
3900                 return true;
3901             },
3902             codeType_);
3903 #else
3904         ExecCtx().ProcessJump(inst_.GetAddress(), target, codeType_);
3905 #endif
3906         return true;
3907     }
3908 
3909     template <BytecodeInstructionSafe::Format FORMAT, template <typename OpT> class Op>
HandleCondJmpz()3910     bool HandleCondJmpz()
3911     {
3912         auto imm = inst_.GetImm<FORMAT>();
3913 
3914         if (!CheckRegType(ACC, integral32_)) {
3915             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3916             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3917             return false;
3918         }
3919 
3920         if (!ProcessBranching(imm)) {
3921             return false;
3922         }
3923 
3924         MoveToNextInst<FORMAT>();
3925         return true;
3926     }
3927 
3928     template <BytecodeInstructionSafe::Format FORMAT, template <typename OpT> class Op>
HandleCondJmp()3929     bool HandleCondJmp()
3930     {
3931         auto imm = inst_.GetImm<FORMAT>();
3932         uint16_t vs = inst_.GetVReg<FORMAT>();
3933 
3934         if (!CheckRegType(ACC, integral32_)) {
3935             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3936             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3937             return false;
3938         }
3939 
3940         if (!CheckRegType(vs, integral32_)) {
3941             SET_STATUS_FOR_MSG(BadRegisterType, WARNING);
3942             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3943             return false;
3944         }
3945 
3946         if (!ProcessBranching(imm)) {
3947             return false;
3948         }
3949 
3950         MoveToNextInst<FORMAT>();
3951         return true;
3952     }
3953 
3954     template <BytecodeInstructionSafe::Format FORMAT>
CheckArrayCtor(Type klass,Span<int> regNums)3955     bool CheckArrayCtor(Type klass, Span<int> regNums)
3956     {
3957         if (!klass.IsConsistent() || !klass.IsClass() || !klass.GetClass()->IsArrayClass()) {
3958             return false;
3959         }
3960         auto argsNum = GetArrayNumDimensions(klass.GetClass());
3961         bool result = false;
3962         for (auto reg : regNums) {
3963             if (!IsRegDefined(reg)) {
3964                 SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
3965                 result = false;
3966                 break;
3967             }
3968             result = CheckRegType(reg, i32_);
3969             if (!result) {
3970                 LOG(ERROR, VERIFIER) << "Verifier error: ArrayCtor type error";
3971                 status_ = VerificationStatus::ERROR;
3972                 break;
3973             }
3974             --argsNum;
3975             if (argsNum == 0) {
3976                 break;
3977             }
3978         };
3979         if (result && argsNum > 0) {
3980             SHOW_MSG(TooFewArrayConstructorArgs)
3981             LOG_VERIFIER_TOO_FEW_ARRAY_CONSTRUCTOR_ARGS(argsNum);
3982             END_SHOW_MSG();
3983             SET_STATUS_FOR_MSG(TooFewArrayConstructorArgs, WARNING);
3984             result = false;
3985         }
3986         if (result) {
3987             SetAcc(klass);
3988             MoveToNextInst<FORMAT>();
3989         }
3990         return result;
3991     }
3992 
LogInnerMessage(const CheckResult & elt)3993     void LogInnerMessage(const CheckResult &elt)
3994     {
3995         if (elt.IsError()) {
3996             LOG(ERROR, VERIFIER) << "Error: " << elt.msg << ". ";
3997         } else if (elt.IsWarning()) {
3998             LOG(WARNING, VERIFIER) << "Warning: " << elt.msg << ". ";
3999         }
4000     }
4001 
GetArrayNumDimensions(Class const * klass)4002     size_t GetArrayNumDimensions(Class const *klass)
4003     {
4004         size_t res = 0;
4005         while (klass->IsArrayClass()) {
4006             res++;
4007             klass = klass->GetComponentType();
4008         }
4009         return res;
4010     }
4011 
CheckFieldAccessStaticVolatile(bool isStatic,bool isVolatile,Field const * & field)4012     bool CheckFieldAccessStaticVolatile(bool isStatic, bool isVolatile, Field const *&field)
4013     {
4014         if (isStatic != field->IsStatic()) {
4015             SHOW_MSG(ExpectedStaticOrInstanceField)
4016             LOG_VERIFIER_EXPECTED_STATIC_OR_INSTANCE_FIELD(isStatic);
4017             END_SHOW_MSG();
4018             SET_STATUS_FOR_MSG(ExpectedStaticOrInstanceField, WARNING);
4019             return false;
4020         }
4021 
4022         if (isVolatile != field->IsVolatile()) {
4023             // if the inst is volatile but the field is not
4024             if (isVolatile) {
4025                 SHOW_MSG(ExpectedVolatileField)
4026                 LOG_VERIFIER_EXPECTED_VOLATILE_FIELD();
4027                 END_SHOW_MSG();
4028                 SET_STATUS_FOR_MSG(ExpectedVolatileField, WARNING);
4029                 return false;
4030             }
4031             // if the instruction is not volatile but the field is
4032             SHOW_MSG(ExpectedInstanceField)
4033             LOG_VERIFIER_EXPECTED_INSTANCE_FIELD();
4034             END_SHOW_MSG();
4035             SET_STATUS_FOR_MSG(ExpectedInstanceField, ERROR);
4036             return false;
4037         }
4038 
4039         return true;
4040     }
4041 
CheckFieldAccessPlugin(Field const * & field)4042     bool CheckFieldAccessPlugin(Field const *&field)
4043     {
4044         auto *plugin = job_->JobPlugin();
4045         auto const *jobMethod = job_->JobMethod();
4046         auto result = plugin->CheckFieldAccessViolation(field, jobMethod, GetTypeSystem());
4047         if (!result.IsOk()) {
4048             const auto &verifOpts = config->opts;
4049             if (verifOpts.debug.allow.fieldAccessViolation && result.IsError()) {
4050                 result.status = VerificationStatus::WARNING;
4051             }
4052             LogInnerMessage(result);
4053             LOG_VERIFIER_DEBUG_FIELD2(GetFieldName(field));
4054             status_ = result.status;
4055             return status_ != VerificationStatus::ERROR;
4056         }
4057 
4058         return !result.IsError();
4059     }
4060 
CheckFieldAccessByNameStartCheck(int regIdx,Field const * & rawField,Type & objType)4061     bool CheckFieldAccessByNameStartCheck(int regIdx, Field const *&rawField, Type &objType)
4062     {
4063         if (rawField == nullptr) {
4064             SET_STATUS_FOR_MSG(CannotResolveFieldId, OK);
4065             return false;
4066         }
4067 
4068         if (rawField->IsStatic()) {
4069             SHOW_MSG(ExpectedStaticOrInstanceField)
4070             LOG_VERIFIER_EXPECTED_STATIC_OR_INSTANCE_FIELD(false);
4071             END_SHOW_MSG();
4072             SET_STATUS_FOR_MSG(ExpectedStaticOrInstanceField, WARNING);
4073             return false;
4074         }
4075 
4076         if (!GetFieldType().IsConsistent()) {
4077             LOG_VERIFIER_CANNOT_RESOLVE_FIELD_TYPE(GetFieldName(rawField));
4078             return false;
4079         }
4080 
4081         if (!IsRegDefined(regIdx)) {
4082             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
4083             return false;
4084         }
4085         objType = GetRegType(regIdx);
4086         if (objType == nullRefType_) {
4087             // NOTE(vdyadov): redesign next code, after support exception handlers,
4088             //                treat it as always throw NPE
4089             SHOW_MSG(AlwaysNpe)
4090             LOG_VERIFIER_ALWAYS_NPE(regIdx);
4091             END_SHOW_MSG();
4092             SET_STATUS_FOR_MSG(AlwaysNpe, OK);
4093             return false;
4094         }
4095 
4096         if (!objType.IsClass()) {
4097             SHOW_MSG(BadRegisterType)
4098             LOG_VERIFIER_BAD_REGISTER_CLASS_TYPE(RegisterName(regIdx, true), ToString(objType));
4099             END_SHOW_MSG();
4100             return false;
4101         }
4102 
4103         return true;
4104     }
4105 
CheckCastArrayObjectRegDef(Type & cachedType)4106     bool CheckCastArrayObjectRegDef(Type &cachedType)
4107     {
4108         if (!cachedType.IsConsistent()) {
4109             return false;
4110         }
4111         LOG_VERIFIER_DEBUG_TYPE(ToString(cachedType));
4112         if (!IsSubtype(cachedType, objectType_, GetTypeSystem()) &&
4113             !IsSubtype(cachedType, arrayType_, GetTypeSystem())) {
4114             LOG_VERIFIER_CHECK_CAST_TO_NON_OBJECT_TYPE(ToString(cachedType));
4115             SET_STATUS_FOR_MSG(CheckCastToNonObjectType, WARNING);
4116             return false;
4117         }
4118         if (!IsRegDefined(ACC)) {
4119             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
4120             return false;
4121         }
4122 
4123         return true;
4124     }
4125 
CheckCastRefArrayType(Type & accType)4126     bool CheckCastRefArrayType(Type &accType)
4127     {
4128         if (!IsSubtype(accType, refType_, GetTypeSystem()) && !IsSubtype(accType, arrayType_, GetTypeSystem())) {
4129             LOG_VERIFIER_NON_OBJECT_ACCUMULATOR_TYPE();
4130             SET_STATUS_FOR_MSG(NonObjectAccumulatorType, WARNING);
4131             return false;
4132         }
4133 
4134         return true;
4135     }
4136 
CheckInstanceConsistentArrayObjectRegDef(Type & cachedType)4137     bool CheckInstanceConsistentArrayObjectRegDef(Type &cachedType)
4138     {
4139         if (!cachedType.IsConsistent()) {
4140             return false;
4141         }
4142         LOG_VERIFIER_DEBUG_TYPE(ToString(cachedType));
4143         if (!IsSubtype(cachedType, objectType_, GetTypeSystem()) &&
4144             !IsSubtype(cachedType, arrayType_, GetTypeSystem())) {
4145             // !(type <= Types().ArrayType()) is redundant, because all arrays
4146             // are subtypes of either panda.Object <: ObjectType or java.lang.Object <: ObjectType
4147             // depending on selected language context
4148             LOG_VERIFIER_BAD_IS_INSTANCE_INSTRUCTION(ToString(cachedType));
4149             SET_STATUS_FOR_MSG(BadIsInstanceInstruction, WARNING);
4150             return false;
4151         }
4152         if (!IsRegDefined(ACC)) {
4153             SET_STATUS_FOR_MSG(UndefinedRegister, WARNING);
4154             return false;
4155         }
4156 
4157         return true;
4158     }
4159 
CheckInstanceClass(Type & cachedType,const plugin::Plugin * & plugin,Method const * & jobMethod)4160     bool CheckInstanceClass(Type &cachedType, const plugin::Plugin *&plugin, Method const *&jobMethod)
4161     {
4162         auto result = CheckResult::ok;
4163         if (cachedType.IsClass()) {
4164             result = plugin->CheckClassAccessViolation(cachedType.GetClass(), jobMethod, GetTypeSystem());
4165         }
4166         if (!result.IsOk()) {
4167             LogInnerMessage(CheckResult::protected_class);
4168             LOG_VERIFIER_DEBUG_CALL_FROM_TO(job_->JobMethod()->GetClass()->GetName(), ToString(cachedType));
4169             status_ = VerificationStatus::ERROR;
4170             return false;
4171         }
4172 
4173         return true;
4174     }
4175 
4176     template <typename NameGetter>
CheckMethodArgsSubtypePrimitive(NameGetter & nameGetter,Type & formalType,Type & actualType,int regNum)4177     bool CheckMethodArgsSubtypePrimitive(NameGetter &nameGetter, Type &formalType, Type &actualType, int regNum)
4178     {
4179         // check implicit conversion of primitive types
4180         TypeId formalId = formalType.ToTypeId();
4181         CheckResult checkResult = CheckResult::ok;
4182 
4183         if (!IsSubtype(actualType, primitive_, GetTypeSystem())) {
4184             return false;
4185         }
4186         // !!!!!! NOTE: need to check all possible TypeId-s against formal_id
4187         TypeId actualId = actualType.ToTypeId();
4188         if (actualId != TypeId::INVALID) {
4189             checkResult = ark::verifier::CheckMethodArgs(formalId, actualId);
4190         } else {
4191             // special case, where type after contexts LUB operation is inexact one, like
4192             // integral32_Type()
4193             if ((IsSubtype(formalType, integral32_, GetTypeSystem()) &&
4194                  IsSubtype(actualType, integral32_, GetTypeSystem())) ||
4195                 (IsSubtype(formalType, integral64_, GetTypeSystem()) &&
4196                  IsSubtype(actualType, integral64_, GetTypeSystem())) ||
4197                 (IsSubtype(formalType, float64_, GetTypeSystem()) &&
4198                  IsSubtype(actualType, float64_, GetTypeSystem()))) {
4199                 SHOW_MSG(CallFormalActualDifferent)
4200                 LOG_VERIFIER_CALL_FORMAL_ACTUAL_DIFFERENT(ToString(formalType), ToString(actualType));
4201                 END_SHOW_MSG();
4202             } else {
4203                 checkResult = ark::verifier::CheckMethodArgs(formalId, actualId);
4204             }
4205         }
4206         if (!checkResult.IsOk()) {
4207             SHOW_MSG(DebugCallParameterTypes)
4208             LogInnerMessage(checkResult);
4209             LOG_VERIFIER_DEBUG_CALL_PARAMETER_TYPES(
4210                 nameGetter(),
4211                 (regNum == INVALID_REG ? "" : PandaString {"Actual parameter in "} + RegisterName(regNum) + ". "),
4212                 ToString(actualType), ToString(formalType));
4213             END_SHOW_MSG();
4214             status_ = checkResult.status;
4215             if (status_ == VerificationStatus::ERROR) {
4216                 return false;
4217             }
4218         }
4219 
4220         return true;
4221     }
4222 
4223     template <typename NameGetter>
CheckMethodArgsIncompatibleTypes(NameGetter & nameGetter,int regNum,Type & actualType,Type & formalType)4224     bool CheckMethodArgsIncompatibleTypes(NameGetter &nameGetter, int regNum, Type &actualType, Type &formalType)
4225     {
4226         auto const normType = GetTypeSystem()->NormalizedTypeOf(formalType);
4227         Type normActualType = GetTypeSystem()->NormalizedTypeOf(actualType);
4228 
4229         PandaString regOrParam = regNum == INVALID_REG ? "Actual parameter" : RegisterName(regNum, true);
4230         SHOW_MSG(BadCallIncompatibleParameter)
4231         LOG_VERIFIER_BAD_CALL_INCOMPATIBLE_PARAMETER(nameGetter(), regOrParam, ToString(normActualType),
4232                                                      ToString(normType));
4233         END_SHOW_MSG();
4234         SET_STATUS_FOR_MSG(BadCallIncompatibleParameter, WARNING);
4235         return false;
4236     }
4237 
4238     template <typename NameGetter>
CheckMethodArgsBot(NameGetter & nameGetter,Type & actualType)4239     bool CheckMethodArgsBot(NameGetter &nameGetter, Type &actualType)
4240     {
4241         if (actualType == Type::Bot()) {
4242             LOG_VERIFIER_CALL_FORMAL_ACTUAL_BOTH_BOT_OR_TOP("Bot");
4243             return true;
4244         }
4245 
4246         SHOW_MSG(BadCallFormalIsBot)
4247         LOG_VERIFIER_BAD_CALL_FORMAL_IS_BOT(nameGetter(), ToString(actualType));
4248         END_SHOW_MSG();
4249         SET_STATUS_FOR_MSG(BadCallFormalIsBot, WARNING);
4250         return false;
4251     }
4252 
CheckMethodArgsTop(Type & actualType)4253     bool CheckMethodArgsTop(Type &actualType)
4254     {
4255         if (actualType == Type::Top()) {
4256             LOG_VERIFIER_CALL_FORMAL_ACTUAL_BOTH_BOT_OR_TOP("Top");
4257             return true;
4258         }
4259         SHOW_MSG(CallFormalTop)
4260         LOG_VERIFIER_CALL_FORMAL_TOP();
4261         END_SHOW_MSG();
4262         return true;
4263     }
4264 
4265     template <typename NameGetter>
CheckMethodArgsCheckType(NameGetter & nameGetter,Type & actualType,Type & formalType,int regNum)4266     void CheckMethodArgsCheckType(NameGetter &nameGetter, Type &actualType, Type &formalType, int regNum)
4267     {
4268         if (regNum == INVALID_REG) {
4269             SHOW_MSG(BadCallWrongParameter)
4270             LOG_VERIFIER_BAD_CALL_WRONG_PARAMETER(nameGetter(), ToString(actualType), ToString(formalType));
4271             END_SHOW_MSG();
4272             SET_STATUS_FOR_MSG(BadCallWrongParameter, WARNING);
4273             return;
4274         }
4275         SHOW_MSG(BadCallWrongRegister)
4276         LOG_VERIFIER_BAD_CALL_WRONG_REGISTER(nameGetter(), regNum);
4277         END_SHOW_MSG();
4278         SET_STATUS_FOR_MSG(BadCallWrongRegister, WARNING);
4279     }
4280 
4281     template <typename NameGetter>
CheckMethodArgsTooFewParmeters(NameGetter & nameGetter)4282     bool CheckMethodArgsTooFewParmeters(NameGetter &nameGetter)
4283     {
4284         SHOW_MSG(BadCallTooFewParameters)
4285         LOG_VERIFIER_BAD_CALL_TOO_FEW_PARAMETERS(nameGetter());
4286         END_SHOW_MSG();
4287         SET_STATUS_FOR_MSG(BadCallTooFewParameters, WARNING);
4288         return false;
4289     }
4290 
CheckMethodArgsNotFit(Type & formalType,Type & actualType,int regNum,bool & incompatibleTypes)4291     bool CheckMethodArgsNotFit(Type &formalType, Type &actualType, int regNum, bool &incompatibleTypes)
4292     {
4293         auto const normType = GetTypeSystem()->NormalizedTypeOf(formalType);
4294         Type normActualType = GetTypeSystem()->NormalizedTypeOf(actualType);
4295 
4296         if (regNum != INVALID_REG && IsSubtype(formalType, refType_, GetTypeSystem()) && formalType != Type::Bot() &&
4297             IsSubtype(actualType, refType_, GetTypeSystem())) {
4298             if (IsSubtype(actualType, formalType, GetTypeSystem())) {
4299                 return true;
4300             }
4301             if (!config->opts.debug.allow.wrongSubclassingInMethodArgs) {
4302                 incompatibleTypes = true;
4303             }
4304         } else if (formalType != Type::Bot() && formalType != Type::Top() &&
4305                    !IsSubtype(normActualType, normType, GetTypeSystem())) {
4306             incompatibleTypes = true;
4307         }
4308 
4309         return false;
4310     }
4311 
4312 private:
4313     BytecodeInstructionSafe inst_;
4314     VerificationContext &context_;
4315     VerificationStatus status_ {VerificationStatus::OK};
4316     // #ifndef NDEBUG
4317     bool debug_ {false};
4318     uint32_t debugOffset_ {0};
4319     // #endif
4320     EntryPointType codeType_;
4321 
SetStatusAtLeast(VerificationStatus newStatus)4322     void SetStatusAtLeast(VerificationStatus newStatus)
4323     {
4324         status_ = std::max(status_, newStatus);
4325     }
4326 
MsgClassToStatus(MethodOption::MsgClass msgClass)4327     static inline VerificationStatus MsgClassToStatus(MethodOption::MsgClass msgClass)
4328     {
4329         switch (msgClass) {
4330             case MethodOption::MsgClass::HIDDEN:
4331                 return VerificationStatus::OK;
4332             case MethodOption::MsgClass::WARNING:
4333                 return VerificationStatus::WARNING;
4334             case MethodOption::MsgClass::ERROR:
4335                 return VerificationStatus::ERROR;
4336             default:
4337                 UNREACHABLE();
4338         }
4339     }
4340 
GetFieldName(Field const * field)4341     static PandaString GetFieldName(Field const *field)
4342     {
4343         return PandaString {field->GetClass()->GetName()} + "." + utf::Mutf8AsCString(field->GetName().data);
4344     }
4345 };
4346 }  // namespace ark::verifier
4347 
4348 #endif  // PANDA_VERIFICATION_ABSINT_ABS_INT_INL_H
4349