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 ¶m) {
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