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