• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "panda_types.h"
17 
18 #include "runtime/include/class_linker.h"
19 #include "runtime/include/method.h"
20 #include "runtime/include/method-inl.h"
21 #include "runtime/include/class.h"
22 #include "runtime/include/runtime.h"
23 
24 #include "utils/span.h"
25 #include "verification/type/type_params.h"
26 #include "verification/type/type_system.h"
27 #include "verification/type/type_sort.h"
28 #include "verification/type/type_image.h"
29 #include "verification/jobs/cache.h"
30 
31 #include "verifier_messages.h"
32 
33 #include "utils/logger.h"
34 
35 #include "runtime/include/mem/panda_containers.h"
36 #include "runtime/include/mem/panda_string.h"
37 
38 #include "libpandabase/os/mutex.h"
39 
40 namespace panda::verifier {
41 
NormalizedTypeOf(Type type)42 Type PandaTypes::NormalizedTypeOf(Type type)
43 {
44     ASSERT(type.IsValid());
45     if (type.IsBot() || type.IsTop()) {
46         return type;
47     }
48     auto t = NormalizedTypeOf_.find(type);
49     if (t != NormalizedTypeOf_.cend()) {
50         return t->second;
51     }
52     Type result = type;
53     if (type <= Integral32Type()) {
54         result = Normalize()(~Integral32Type());
55         NormalizedTypeOf_[type] = result;
56     } else if (type <= Integral64Type()) {
57         result = Normalize()(~Integral64Type());
58         NormalizedTypeOf_[type] = result;
59         // NOLINTNEXTLINE(bugprone-branch-clone)
60     } else if (type <= F32()) {
61         result = Normalize()(~F32());
62         NormalizedTypeOf_[type] = result;
63     } else if (type <= F64()) {
64         result = Normalize()(~F64());
65         NormalizedTypeOf_[type] = result;
66     } else if (type <= MethodType()) {
67         result = NormalizedMethod()(NormalizeMethodSignature(type.Params()));
68     }
69     NormalizedTypeOf_[type] = result;
70     return result;
71 }
72 
NormalizeMethodSignature(const TypeParams & sig)73 TypeParams PandaTypes::NormalizeMethodSignature(const TypeParams &sig)
74 {
75     TypeParams result {TypeSystemKind::JAVA, threadnum_};
76     sig.ForEach([&result, this](const auto &param) {
77         const Type &type = param;
78         result >> (NormalizedTypeOf(type) * param.Variance());
79     });
80     return result;
81 }
82 
NormalizedMethodSignature(const CachedMethod & method)83 const TypeParams &PandaTypes::NormalizedMethodSignature(const CachedMethod &method)
84 {
85     auto &&method_id = method.id;
86     auto it = NormalizedSigOfMethod_.find(method_id);
87     if (it != NormalizedSigOfMethod_.end()) {
88         return it->second;
89     }
90     auto &&sig = MethodSignature(method);
91     auto &&normalized_sig = NormalizeMethodSignature(sig);
92     NormalizedSigOfMethod_[method_id] = normalized_sig;
93     return NormalizedSigOfMethod_[method_id];
94 }
95 
MethodSignature(const CachedMethod & method)96 const TypeParams &PandaTypes::MethodSignature(const CachedMethod &method)
97 {
98     auto &&method_id = method.id;
99     auto it = SigOfMethod_.find(method_id);
100     if (it != SigOfMethod_.end()) {
101         return it->second;
102     }
103     TypeParams params {TypeSystemKind::JAVA, threadnum_};
104     Type return_type;
105     bool return_is_processed = false;
106     for (const auto &arg : method.signature) {
107         Type t = LibCache::Visit(
108             arg,
109             [this](const LibCache::CachedClass &cached_class) {
110                 return cached_class.type_id == TypeId::VOID ? Top() : TypeOf(cached_class);
111             },
112             [&]([[maybe_unused]] const LibCache::DescriptorString &descriptor) {
113                 LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_WAS_NOT_RESOLVED(method.GetName());
114                 return Top();
115             });
116 
117         if (!t.IsValid()) {
118             LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_CANNOT_BE_CONVERTED_TO_TYPE(method.GetName());
119         }
120         if (return_is_processed) {
121             params >> -t;
122         } else {
123             return_type = t;
124             return_is_processed = true;
125         }
126     }
127     params >> +return_type;
128     SigOfMethod_[method_id] = params;
129     return SigOfMethod_[method_id];
130 }
131 
TypeIdOf(const Type & type) const132 PandaTypes::TypeId PandaTypes::TypeIdOf(const Type &type) const
133 {
134     if (type == U1()) {
135         return TypeId::U1;
136     }
137     if (type == U8()) {
138         return TypeId::U8;
139     }
140     if (type == U16()) {
141         return TypeId::U16;
142     }
143     if (type == U32()) {
144         return TypeId::U32;
145     }
146     if (type == U64()) {
147         return TypeId::U64;
148     }
149     if (type == I8()) {
150         return TypeId::I8;
151     }
152     if (type == I16()) {
153         return TypeId::I16;
154     }
155     if (type == I32()) {
156         return TypeId::I32;
157     }
158     if (type == I64()) {
159         return TypeId::I64;
160     }
161     if (type == F32()) {
162         return TypeId::F32;
163     }
164     if (type == F64()) {
165         return TypeId::F64;
166     }
167     if (type.IsTop()) {
168         return TypeId::VOID;
169     }
170 
171     return TypeId::INVALID;
172 }
173 
TypeOf(const CachedMethod & method)174 Type PandaTypes::TypeOf(const CachedMethod &method)
175 {
176     auto id = method.id;
177     auto k = TypeOfMethod_.find(id);
178     if (k != TypeOfMethod_.end()) {
179         return k->second;
180     }
181     ASSERT(!DoNotCalculateMethodType_);
182     auto &&sig = MethodSignature(method);
183     auto &&norm_sig = NormalizedMethodSignature(method);
184     Type type;
185     type = Method()(sig);
186     type << MethodType();
187     TypeOfMethod_[id] = type;
188     // Normalize(Method) <: NormalizedMethod(NormalizedMethodSig)
189     auto norm_type = Normalize()(~type);
190     auto norm_method = NormalizedMethod()(norm_sig);
191     norm_type << norm_method;
192     NormalizedTypeOf_[type] = norm_method;
193     MethodNameOfId_[id] = method.GetName();
194     return type;
195 }
196 
SetArraySubtyping(const Type & t)197 void PandaTypes::SetArraySubtyping(const Type &t)
198 {
199     PandaVector<Type> to_process;
200     PandaVector<Type> just_subtype;
201     t.ForAllSupertypes([&]([[maybe_unused]] const Type &st) {
202         if (!Array()[+st]) {
203             to_process.emplace_back(st);
204         } else {
205             just_subtype.emplace_back(st);
206         }
207         return true;
208     });
209     auto array_type = Array()(+t);
210     for (const auto &st : just_subtype) {
211         array_type << Array()(+st);
212     }
213     for (const auto &st : to_process) {
214         array_type << Array()(+st);
215         SetArraySubtyping(st);
216     }
217 }
218 
TypeOfArray(const CachedClass & klass)219 Type PandaTypes::TypeOfArray(const CachedClass &klass)
220 {
221     ASSERT(klass.flags[CachedClass::Flag::ARRAY_CLASS]);
222 
223     Type type;
224     auto component = klass.GetArrayComponent();
225     if (component.HasRef()) {
226         auto component_type = TypeOf(component.Get());
227         type = Array()(+component_type);
228         SetArraySubtyping(component_type);
229     } else {
230         type = Array()(+Top());
231         LOG_VERIFIER_JAVA_TYPES_ARRAY_COMPONENT_TYPE_IS_UNDEFINED();
232     }
233     type << ArrayType();
234     if (klass.flags[CachedClass::Flag::OBJECT_ARRAY_CLASS]) {
235         type << ObjectArrayType();
236     }
237 
238     return type;
239 }
240 
TypeOf(const CachedClass & klass)241 Type PandaTypes::TypeOf(const CachedClass &klass)
242 {
243     auto id = klass.id;
244     auto k = TypeOfClass_.find(id);
245     if (k != TypeOfClass_.end()) {
246         return k->second;
247     }
248 
249     PandaVector<Type> supertypes;
250     for (const auto &ancestor : klass.ancestors) {
251         // ancestor here cannot be unresolved descriptor
252         ASSERT(LibCache::IsRef(ancestor));
253         supertypes.emplace_back(TypeOf(LibCache::GetRef(ancestor)));
254     }
255 
256     Type type;
257     bool is_primitive = klass.flags[CachedClass::Flag::PRIMITIVE];
258 
259     auto class_name = klass.GetName();
260 
261     if (klass.flags[CachedClass::Flag::ARRAY_CLASS]) {
262         type = TypeOfArray(klass);
263     } else if (is_primitive) {
264         type = TypeOf(klass.type_id);
265     } else {
266         type = TypeForName(class_name);
267     }
268 
269     if (!is_primitive) {
270         bool is_string = klass.flags[CachedClass::Flag::STRING_CLASS];
271         if (is_string) {
272             type << StringType();
273         } else {
274             type << ObjectType();
275         }
276         NullRefType() << type << RefType();
277         TypeClass()(~type) << TypeClassType() << RefType();
278     }
279     if (klass.flags[CachedClass::Flag::ABSTRACT]) {
280         Abstract()(~type) << AbstractType();
281     }
282     for (auto &super : supertypes) {
283         type << super;
284     }
285     ClassNameOfId_[id] = class_name;
286     TypeOfClass_[id] = type;
287     NormalizedTypeOf(type);
288     return type;
289 }
290 
TypeOf(PandaTypes::TypeId id) const291 Type PandaTypes::TypeOf(PandaTypes::TypeId id) const
292 {
293     Type type;
294     switch (id) {
295         case TypeId::VOID:
296             type = Top();
297             break;
298         case TypeId::U1:
299             type = U1();
300             break;
301         case TypeId::I8:
302             type = I8();
303             break;
304         case TypeId::U8:
305             type = U8();
306             break;
307         case TypeId::I16:
308             type = I16();
309             break;
310         case TypeId::U16:
311             type = U16();
312             break;
313         case TypeId::I32:
314             type = I32();
315             break;
316         case TypeId::U32:
317             type = U32();
318             break;
319         case TypeId::I64:
320             type = I64();
321             break;
322         case TypeId::U64:
323             type = U64();
324             break;
325         case TypeId::F32:
326             type = F32();
327             break;
328         case TypeId::F64:
329             type = F64();
330             break;
331         case TypeId::REFERENCE:
332             type = RefType();
333             break;
334         default:
335             LOG_VERIFIER_JAVA_TYPES_CANNOT_CONVERT_TYPE_ID_TO_TYPE(id);
336             type = Top();
337     }
338     return type;
339 }
340 
PandaTypes(ThreadNum threadnum)341 PandaTypes::PandaTypes(ThreadNum threadnum)
342     : threadnum_ {threadnum},
343       TypeSystem_ {TypeSystems::Get(TypeSystemKind::JAVA, threadnum_)},
344       Array_ {ParametricTypeForName("Array")},
345       Method_ {ParametricTypeForName("Method")},
346       NormalizedMethod_ {ParametricTypeForName("NormalizedMethod")},
347       Normalize_ {ParametricTypeForName("Normalize")},
348       Abstract_ {ParametricTypeForName("Abstract")},
349       Interface_ {ParametricTypeForName("Interface")},
350       TypeClass_ {ParametricTypeForName("TypeClass")},
351 
352       U1_ {TypeForName("u1")},
353       I8_ {TypeForName("i8")},
354       U8_ {TypeForName("u8")},
355       I16_ {TypeForName("i16")},
356       U16_ {TypeForName("u16")},
357       I32_ {TypeForName("i32")},
358       U32_ {TypeForName("u32")},
359       I64_ {TypeForName("i64")},
360       U64_ {TypeForName("u64")},
361       F32_ {TypeForName("f32")},
362       F64_ {TypeForName("f64")},
363 
364       RefType_ {TypeForName("RefType")},
365       ObjectType_ {TypeForName("ObjectType")},
366       StringType_ {TypeForName("StringType")},
367       PrimitiveType_ {TypeForName("PrimitiveType")},
368       AbstractType_ {TypeForName("AbstractType")},
369       InterfaceType_ {TypeForName("InterfaceType")},
370       TypeClassType_ {TypeForName("TypeClassType")},
371       InstantiableType_ {TypeForName("InstantiableType")},
372       ArrayType_ {TypeForName("ArrayType")},
373       ObjectArrayType_ {TypeForName("ObjectArrayType")},
374       MethodType_ {TypeForName("MethodType")},
375       StaticMethodType_ {TypeForName("StaticMethodType")},
376       NonStaticMethodType_ {TypeForName("NonStaticMethodType")},
377       VirtualMethodType_ {TypeForName("VirtualMethodType")},
378       NullRefType_ {TypeForName("NullRefType")},
379       Bits32Type_ {TypeForName("32Bits")},
380       Bits64Type_ {TypeForName("64Bits")},
381       Integral8Type_ {TypeForName("Integral8Bits")},
382       Integral16Type_ {TypeForName("Integral16Bits")},
383       Integral32Type_ {TypeForName("Integral32Bits")},
384       Integral64Type_ {TypeForName("Integral64Bits")},
385       Float32Type_ {TypeForName("Float32Bits")},
386       Float64Type_ {TypeForName("Float64Bits")}
387 {
388     for (panda::panda_file::SourceLang lang : panda::panda_file::LANG_ITERATOR) {
389         LanguageContextBase *ctx = panda::plugins::GetLanguageContextBase(lang);
390 
__anon4f716ff80502(auto &types, const char *name) 391         auto emplace = [&](auto &types, const char *name) {
392             if (name != nullptr) {
393                 types.emplace(lang, TypeForName(name));
394             }
395         };
396 
397         emplace(LangContextTypesClass_, ctx->GetVerificationTypeClass());
398         emplace(LangContextTypesObjects_, ctx->GetVerificationTypeObject());
399         emplace(LangContextTypesThrowables_, ctx->GetVerificationTypeThrowable());
400     }
401 
402     TypeSystem_.SetIncrementalRelationClosureMode(false);
403 
404     // base subtyping of primitive types
405     I8() << I16() << I32();
406     U1() << U8() << U16() << U32();
407     // integral
408     TypeSet(U1(), I8(), U8()) << Integral8Type();
409     TypeSet(Integral8Type(), I16(), U16()) << Integral16Type();
410     TypeSet(Integral16Type(), I32(), U32()) << Integral32Type();
411     TypeSet(I64(), U64()) << Integral64Type();
412     // sizes
413     F32() << Float32Type();
414     F64() << Float64Type();
415     TypeSet(Integral32Type(), Float32Type()) << Bits32Type();
416     TypeSet(Integral64Type(), Float64Type()) << Bits64Type();
417     TypeSet(Bits32Type(), Bits64Type()) << PrimitiveType();
418 
419     TypeClassType() << RefType();
420 
421     TypeSet object_or_ref(ObjectType(), RefType());
422     for (const auto &[lang, type] : LangContextTypesClass_) {
423         NullRefType() << type << object_or_ref;
424         (void)lang;
425     }
426 
427     for (const auto &[lang, type] : LangContextTypesObjects_) {
428         NullRefType() << type << object_or_ref;
429         (void)lang;
430     }
431 
432     for (const auto &[lang, type] : LangContextTypesThrowables_) {
433         NullRefType() << type << object_or_ref;
434         (void)lang;
435     }
436 
437     NullRefType() << (ArrayType() | ObjectArrayType()) << RefType();
438 
439     for (const auto &[lang, type] : LangContextTypesObjects_) {
440         TypeClass()(~Object(lang)) << TypeClassType();
441         (void)type;
442     }
443 
444     TypeSystem_.CloseSubtypingRelation();
445 
446     TypeSystem_.SetIncrementalRelationClosureMode(false);
447     TypeSystem_.SetDeferIncrementalRelationClosure(false);
448 }
449 
450 }  // namespace panda::verifier
451