1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
18 #define ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
19 
20 #include "reg_type.h"
21 
22 #include "base/casts.h"
23 #include "base/scoped_arena_allocator.h"
24 #include "method_verifier.h"
25 #include "mirror/class.h"
26 #include "verifier_deps.h"
27 
28 namespace art {
29 namespace verifier {
30 
31 inline bool RegType::CanAccess(const RegType& other) const {
32   DCHECK(IsReferenceTypes());
33   DCHECK(!IsNull());
34   if (Equals(other)) {
35     return true;  // Trivial accessibility.
36   } else {
37     bool this_unresolved = IsUnresolvedTypes();
38     bool other_unresolved = other.IsUnresolvedTypes();
39     if (!this_unresolved && !other_unresolved) {
40       return GetClass()->CanAccess(other.GetClass());
41     } else if (!other_unresolved) {
42       return other.GetClass()->IsPublic();  // Be conservative, only allow if other is public.
43     } else {
44       return false;  // More complicated test not possible on unresolved types, be conservative.
45     }
46   }
47 }
48 
49 inline bool RegType::CanAccessMember(ObjPtr<mirror::Class> klass, uint32_t access_flags) const {
50   DCHECK(IsReferenceTypes());
51   if (IsNull()) {
52     return true;
53   }
54   if (!IsUnresolvedTypes()) {
55     return GetClass()->CanAccessMember(klass, access_flags);
56   } else {
57     return false;  // More complicated test not possible on unresolved types, be conservative.
58   }
59 }
60 
61 inline bool RegType::IsConstantBoolean() const {
62   if (!IsConstant()) {
63     return false;
64   } else {
65     const ConstantType* const_val = down_cast<const ConstantType*>(this);
66     return const_val->ConstantValue() >= 0 && const_val->ConstantValue() <= 1;
67   }
68 }
69 
70 inline bool RegType::AssignableFrom(const RegType& lhs,
71                                     const RegType& rhs,
72                                     bool strict,
73                                     MethodVerifier* verifier) {
74   if (lhs.Equals(rhs)) {
75     return true;
76   } else {
77     switch (lhs.GetAssignmentType()) {
78       case AssignmentType::kBoolean:
79         return rhs.IsBooleanTypes();
80       case AssignmentType::kByte:
81         return rhs.IsByteTypes();
82       case AssignmentType::kShort:
83         return rhs.IsShortTypes();
84       case AssignmentType::kChar:
85         return rhs.IsCharTypes();
86       case AssignmentType::kInteger:
87         return rhs.IsIntegralTypes();
88       case AssignmentType::kFloat:
89         return rhs.IsFloatTypes();
90       case AssignmentType::kLongLo:
91         return rhs.IsLongTypes();
92       case AssignmentType::kDoubleLo:
93         return rhs.IsDoubleTypes();
94       case AssignmentType::kConflict:
95         LOG(WARNING) << "RegType::AssignableFrom lhs is Conflict!";
96         return false;
97       case AssignmentType::kReference:
98         if (rhs.IsZeroOrNull()) {
99           return true;  // All reference types can be assigned null.
100         } else if (!rhs.IsReferenceTypes()) {
101           return false;  // Expect rhs to be a reference type.
102         } else if (lhs.IsUninitializedTypes() || rhs.IsUninitializedTypes()) {
103           // Uninitialized types are only allowed to be assigned to themselves.
104           // TODO: Once we have a proper "reference" super type, this needs to be extended.
105           return false;
106         } else if (lhs.IsJavaLangObject()) {
107           return true;  // All reference types can be assigned to Object.
108         } else if (!strict && !lhs.IsUnresolvedTypes() && lhs.GetClass()->IsInterface()) {
109           // If we're not strict allow assignment to any interface, see comment in ClassJoin.
110           return true;
111         } else if (lhs.IsJavaLangObjectArray()) {
112           return rhs.IsObjectArrayTypes();  // All reference arrays may be assigned to Object[]
113         } else if (lhs.HasClass() && rhs.HasClass()) {
114           // Test assignability from the Class point-of-view.
115           bool result = lhs.GetClass()->IsAssignableFrom(rhs.GetClass());
116           // Record assignability dependency. The `verifier` is null during unit tests and
117           // VerifiedMethod::GenerateSafeCastSet.
118           if (verifier != nullptr && result) {
119             VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
120                                                    verifier->GetDexFile(),
121                                                    verifier->GetClassDef(),
122                                                    lhs.GetClass(),
123                                                    rhs.GetClass());
124           }
125           return result;
126         } else {
127           // For unresolved types, we don't know if they are assignable, and the
128           // verifier will continue assuming they are. We need to record that.
129           if (verifier != nullptr) {
130             VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
131                                                    verifier->GetDexFile(),
132                                                    verifier->GetClassDef(),
133                                                    lhs,
134                                                    rhs);
135           }
136           // Unresolved types are only assignable for null and equality.
137           // Null cannot be the left-hand side.
138           return false;
139         }
140       case AssignmentType::kNotAssignable:
141         break;
142     }
143     LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '"
144                << lhs << "' := '" << rhs << "'";
145     UNREACHABLE();
146   }
147 }
148 
149 inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
150   return AssignableFrom(*this, src, false, verifier);
151 }
152 
153 inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
154   return AssignableFrom(*this, src, true, verifier);
155 }
156 
157 inline const DoubleHiType* DoubleHiType::GetInstance() {
158   DCHECK(instance_ != nullptr);
159   return instance_;
160 }
161 
162 inline const DoubleLoType* DoubleLoType::GetInstance() {
163   DCHECK(instance_ != nullptr);
164   return instance_;
165 }
166 
167 inline const LongHiType* LongHiType::GetInstance() {
168   DCHECK(instance_ != nullptr);
169   return instance_;
170 }
171 
172 inline const LongLoType* LongLoType::GetInstance() {
173   DCHECK(instance_ != nullptr);
174   return instance_;
175 }
176 
177 inline const FloatType* FloatType::GetInstance() {
178   DCHECK(instance_ != nullptr);
179   return instance_;
180 }
181 
182 inline const CharType* CharType::GetInstance() {
183   DCHECK(instance_ != nullptr);
184   return instance_;
185 }
186 
187 inline const ShortType* ShortType::GetInstance() {
188   DCHECK(instance_ != nullptr);
189   return instance_;
190 }
191 
192 inline const ByteType* ByteType::GetInstance() {
193   DCHECK(instance_ != nullptr);
194   return instance_;
195 }
196 
197 
198 inline const IntegerType* IntegerType::GetInstance() {
199   DCHECK(instance_ != nullptr);
200   return instance_;
201 }
202 
203 inline const BooleanType* BooleanType::GetInstance() {
204   DCHECK(BooleanType::instance_ != nullptr);
205   return BooleanType::instance_;
206 }
207 
208 inline const ConflictType* ConflictType::GetInstance() {
209   DCHECK(instance_ != nullptr);
210   return instance_;
211 }
212 
213 inline const UndefinedType* UndefinedType::GetInstance() {
214   DCHECK(instance_ != nullptr);
215   return instance_;
216 }
217 
218 inline const NullType* NullType::GetInstance() {
219   DCHECK(instance_ != nullptr);
220   return instance_;
221 }
222 
223 inline void* RegType::operator new(size_t size, ScopedArenaAllocator* allocator) {
224   return allocator->Alloc(size, kArenaAllocMisc);
225 }
226 
227 }  // namespace verifier
228 }  // namespace art
229 
230 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
231