Home | History | Annotate | Download | only in verifier
      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) {
    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 
    137 inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
    138   return AssignableFrom(*this, src, false, verifier);
    139 }
    140 
    141 inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
    142   return AssignableFrom(*this, src, true, verifier);
    143 }
    144 
    145 inline const DoubleHiType* DoubleHiType::GetInstance() {
    146   DCHECK(instance_ != nullptr);
    147   return instance_;
    148 }
    149 
    150 inline const DoubleLoType* DoubleLoType::GetInstance() {
    151   DCHECK(instance_ != nullptr);
    152   return instance_;
    153 }
    154 
    155 inline const LongHiType* LongHiType::GetInstance() {
    156   DCHECK(instance_ != nullptr);
    157   return instance_;
    158 }
    159 
    160 inline const LongLoType* LongLoType::GetInstance() {
    161   DCHECK(instance_ != nullptr);
    162   return instance_;
    163 }
    164 
    165 inline const FloatType* FloatType::GetInstance() {
    166   DCHECK(instance_ != nullptr);
    167   return instance_;
    168 }
    169 
    170 inline const CharType* CharType::GetInstance() {
    171   DCHECK(instance_ != nullptr);
    172   return instance_;
    173 }
    174 
    175 inline const ShortType* ShortType::GetInstance() {
    176   DCHECK(instance_ != nullptr);
    177   return instance_;
    178 }
    179 
    180 inline const ByteType* ByteType::GetInstance() {
    181   DCHECK(instance_ != nullptr);
    182   return instance_;
    183 }
    184 
    185 
    186 inline const IntegerType* IntegerType::GetInstance() {
    187   DCHECK(instance_ != nullptr);
    188   return instance_;
    189 }
    190 
    191 inline const BooleanType* BooleanType::GetInstance() {
    192   DCHECK(BooleanType::instance_ != nullptr);
    193   return BooleanType::instance_;
    194 }
    195 
    196 inline const ConflictType* ConflictType::GetInstance() {
    197   DCHECK(instance_ != nullptr);
    198   return instance_;
    199 }
    200 
    201 inline const UndefinedType* UndefinedType::GetInstance() {
    202   DCHECK(instance_ != nullptr);
    203   return instance_;
    204 }
    205 
    206 inline const NullType* NullType::GetInstance() {
    207   DCHECK(instance_ != nullptr);
    208   return instance_;
    209 }
    210 
    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