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 
CanAccess(const RegType & other)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 
CanAccessMember(ObjPtr<mirror::Class> klass,uint32_t access_flags)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 
IsConstantBoolean()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 
AssignableFrom(const RegType & lhs,const RegType & rhs,bool strict,MethodVerifier * verifier)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) {
119             VerifierDeps::MaybeRecordAssignability(
120                 verifier->GetDexFile(), lhs.GetClass(), rhs.GetClass(), strict, result);
121           }
122           return result;
123         } else {
124           // Unresolved types are only assignable for null and equality.
125           // Null cannot be the left-hand side.
126           return false;
127         }
128       case AssignmentType::kNotAssignable:
129         break;
130     }
131     LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '"
132                << lhs << "' := '" << rhs << "'";
133     UNREACHABLE();
134   }
135 }
136 
IsAssignableFrom(const RegType & src,MethodVerifier * verifier)137 inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
138   return AssignableFrom(*this, src, false, verifier);
139 }
140 
IsStrictlyAssignableFrom(const RegType & src,MethodVerifier * verifier)141 inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
142   return AssignableFrom(*this, src, true, verifier);
143 }
144 
GetInstance()145 inline const DoubleHiType* DoubleHiType::GetInstance() {
146   DCHECK(instance_ != nullptr);
147   return instance_;
148 }
149 
GetInstance()150 inline const DoubleLoType* DoubleLoType::GetInstance() {
151   DCHECK(instance_ != nullptr);
152   return instance_;
153 }
154 
GetInstance()155 inline const LongHiType* LongHiType::GetInstance() {
156   DCHECK(instance_ != nullptr);
157   return instance_;
158 }
159 
GetInstance()160 inline const LongLoType* LongLoType::GetInstance() {
161   DCHECK(instance_ != nullptr);
162   return instance_;
163 }
164 
GetInstance()165 inline const FloatType* FloatType::GetInstance() {
166   DCHECK(instance_ != nullptr);
167   return instance_;
168 }
169 
GetInstance()170 inline const CharType* CharType::GetInstance() {
171   DCHECK(instance_ != nullptr);
172   return instance_;
173 }
174 
GetInstance()175 inline const ShortType* ShortType::GetInstance() {
176   DCHECK(instance_ != nullptr);
177   return instance_;
178 }
179 
GetInstance()180 inline const ByteType* ByteType::GetInstance() {
181   DCHECK(instance_ != nullptr);
182   return instance_;
183 }
184 
185 
GetInstance()186 inline const IntegerType* IntegerType::GetInstance() {
187   DCHECK(instance_ != nullptr);
188   return instance_;
189 }
190 
GetInstance()191 inline const BooleanType* BooleanType::GetInstance() {
192   DCHECK(BooleanType::instance_ != nullptr);
193   return BooleanType::instance_;
194 }
195 
GetInstance()196 inline const ConflictType* ConflictType::GetInstance() {
197   DCHECK(instance_ != nullptr);
198   return instance_;
199 }
200 
GetInstance()201 inline const UndefinedType* UndefinedType::GetInstance() {
202   DCHECK(instance_ != nullptr);
203   return instance_;
204 }
205 
GetInstance()206 inline const NullType* NullType::GetInstance() {
207   DCHECK(instance_ != nullptr);
208   return instance_;
209 }
210 
new(size_t size,ScopedArenaAllocator * allocator)211 inline void* RegType::operator new(size_t size, ScopedArenaAllocator* allocator) {
212   return allocator->Alloc(size, kArenaAllocMisc);
213 }
214 
215 }  // namespace verifier
216 }  // namespace art
217 
218 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
219