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 HIDDEN {
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 && 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             // Note that if `rhs` is an interface type, `lhs` may be j.l.Object
131             // and if the assignability check is not strict, then this should be
132             // OK. However we don't encode strictness in the verifier deps, and
133             // such a situation will force a full verification.
134             VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
135                                                    verifier->GetDexFile(),
136                                                    verifier->GetClassDef(),
137                                                    lhs,
138                                                    rhs);
139           }
140           // Unresolved types are only assignable for null and equality.
141           // Null cannot be the left-hand side.
142           return false;
143         }
144       case AssignmentType::kNotAssignable:
145         break;
146     }
147     LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '"
148                << lhs << "' := '" << rhs << "'";
149     UNREACHABLE();
150   }
151 }
152 
IsAssignableFrom(const RegType & src,MethodVerifier * verifier)153 inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
154   return AssignableFrom(*this, src, false, verifier);
155 }
156 
IsStrictlyAssignableFrom(const RegType & src,MethodVerifier * verifier)157 inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
158   return AssignableFrom(*this, src, true, verifier);
159 }
160 
new(size_t size,ScopedArenaAllocator * allocator)161 inline void* RegType::operator new(size_t size, ScopedArenaAllocator* allocator) {
162   return allocator->Alloc(size, kArenaAllocMisc);
163 }
164 
165 }  // namespace verifier
166 }  // namespace art
167 
168 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
169