1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2007 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.mockito.asm.tree.analysis; 31 32 import java.util.List; 33 34 import org.mockito.asm.Type; 35 36 /** 37 * An extended {@link BasicVerifier} that performs more precise verifications. 38 * This verifier computes exact class types, instead of using a single "object 39 * reference" type (as done in the {@link BasicVerifier}). 40 * 41 * @author Eric Bruneton 42 * @author Bing Ran 43 */ 44 public class SimpleVerifier extends BasicVerifier { 45 46 /** 47 * The class that is verified. 48 */ 49 private final Type currentClass; 50 51 /** 52 * The super class of the class that is verified. 53 */ 54 private final Type currentSuperClass; 55 56 /** 57 * The interfaces implemented by the class that is verified. 58 */ 59 private final List currentClassInterfaces; 60 61 /** 62 * If the class that is verified is an interface. 63 */ 64 private final boolean isInterface; 65 66 /** 67 * Constructs a new {@link SimpleVerifier}. 68 */ SimpleVerifier()69 public SimpleVerifier() { 70 this(null, null, false); 71 } 72 73 /** 74 * Constructs a new {@link SimpleVerifier} to verify a specific class. This 75 * class will not be loaded into the JVM since it may be incorrect. 76 * 77 * @param currentClass the class that is verified. 78 * @param currentSuperClass the super class of the class that is verified. 79 * @param isInterface if the class that is verified is an interface. 80 */ SimpleVerifier( final Type currentClass, final Type currentSuperClass, final boolean isInterface)81 public SimpleVerifier( 82 final Type currentClass, 83 final Type currentSuperClass, 84 final boolean isInterface) 85 { 86 this(currentClass, currentSuperClass, null, isInterface); 87 } 88 89 /** 90 * Constructs a new {@link SimpleVerifier} to verify a specific class. This 91 * class will not be loaded into the JVM since it may be incorrect. 92 * 93 * @param currentClass the class that is verified. 94 * @param currentSuperClass the super class of the class that is verified. 95 * @param currentClassInterfaces the interfaces implemented by the class 96 * that is verified. 97 * @param isInterface if the class that is verified is an interface. 98 */ SimpleVerifier( final Type currentClass, final Type currentSuperClass, final List currentClassInterfaces, final boolean isInterface)99 public SimpleVerifier( 100 final Type currentClass, 101 final Type currentSuperClass, 102 final List currentClassInterfaces, 103 final boolean isInterface) 104 { 105 this.currentClass = currentClass; 106 this.currentSuperClass = currentSuperClass; 107 this.currentClassInterfaces = currentClassInterfaces; 108 this.isInterface = isInterface; 109 } 110 newValue(final Type type)111 public Value newValue(final Type type) { 112 if (type == null) { 113 return BasicValue.UNINITIALIZED_VALUE; 114 } 115 116 boolean isArray = type.getSort() == Type.ARRAY; 117 if (isArray) { 118 switch (type.getElementType().getSort()) { 119 case Type.BOOLEAN: 120 case Type.CHAR: 121 case Type.BYTE: 122 case Type.SHORT: 123 return new BasicValue(type); 124 } 125 } 126 127 Value v = super.newValue(type); 128 if (v == BasicValue.REFERENCE_VALUE) { 129 if (isArray) { 130 v = newValue(type.getElementType()); 131 String desc = ((BasicValue) v).getType().getDescriptor(); 132 for (int i = 0; i < type.getDimensions(); ++i) { 133 desc = '[' + desc; 134 } 135 v = new BasicValue(Type.getType(desc)); 136 } else { 137 v = new BasicValue(type); 138 } 139 } 140 return v; 141 } 142 isArrayValue(final Value value)143 protected boolean isArrayValue(final Value value) { 144 Type t = ((BasicValue) value).getType(); 145 return t != null 146 && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY); 147 } 148 getElementValue(final Value objectArrayValue)149 protected Value getElementValue(final Value objectArrayValue) 150 throws AnalyzerException 151 { 152 Type arrayType = ((BasicValue) objectArrayValue).getType(); 153 if (arrayType != null) { 154 if (arrayType.getSort() == Type.ARRAY) { 155 return newValue(Type.getType(arrayType.getDescriptor() 156 .substring(1))); 157 } else if ("Lnull;".equals(arrayType.getDescriptor())) { 158 return objectArrayValue; 159 } 160 } 161 throw new Error("Internal error"); 162 } 163 isSubTypeOf(final Value value, final Value expected)164 protected boolean isSubTypeOf(final Value value, final Value expected) { 165 Type expectedType = ((BasicValue) expected).getType(); 166 Type type = ((BasicValue) value).getType(); 167 switch (expectedType.getSort()) { 168 case Type.INT: 169 case Type.FLOAT: 170 case Type.LONG: 171 case Type.DOUBLE: 172 return type == expectedType; 173 case Type.ARRAY: 174 case Type.OBJECT: 175 if ("Lnull;".equals(type.getDescriptor())) { 176 return true; 177 } else if (type.getSort() == Type.OBJECT 178 || type.getSort() == Type.ARRAY) 179 { 180 return isAssignableFrom(expectedType, type); 181 } else { 182 return false; 183 } 184 default: 185 throw new Error("Internal error"); 186 } 187 } 188 merge(final Value v, final Value w)189 public Value merge(final Value v, final Value w) { 190 if (!v.equals(w)) { 191 Type t = ((BasicValue) v).getType(); 192 Type u = ((BasicValue) w).getType(); 193 if (t != null 194 && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) 195 { 196 if (u != null 197 && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) 198 { 199 if ("Lnull;".equals(t.getDescriptor())) { 200 return w; 201 } 202 if ("Lnull;".equals(u.getDescriptor())) { 203 return v; 204 } 205 if (isAssignableFrom(t, u)) { 206 return v; 207 } 208 if (isAssignableFrom(u, t)) { 209 return w; 210 } 211 // TODO case of array classes of the same dimension 212 // TODO should we look also for a common super interface? 213 // problem: there may be several possible common super 214 // interfaces 215 do { 216 if (t == null || isInterface(t)) { 217 return BasicValue.REFERENCE_VALUE; 218 } 219 t = getSuperClass(t); 220 if (isAssignableFrom(t, u)) { 221 return newValue(t); 222 } 223 } while (true); 224 } 225 } 226 return BasicValue.UNINITIALIZED_VALUE; 227 } 228 return v; 229 } 230 isInterface(final Type t)231 protected boolean isInterface(final Type t) { 232 if (currentClass != null && t.equals(currentClass)) { 233 return isInterface; 234 } 235 return getClass(t).isInterface(); 236 } 237 getSuperClass(final Type t)238 protected Type getSuperClass(final Type t) { 239 if (currentClass != null && t.equals(currentClass)) { 240 return currentSuperClass; 241 } 242 Class c = getClass(t).getSuperclass(); 243 return c == null ? null : Type.getType(c); 244 } 245 isAssignableFrom(final Type t, final Type u)246 protected boolean isAssignableFrom(final Type t, final Type u) { 247 if (t.equals(u)) { 248 return true; 249 } 250 if (currentClass != null && t.equals(currentClass)) { 251 if (getSuperClass(u) == null) { 252 return false; 253 } else { 254 return isAssignableFrom(t, getSuperClass(u)); 255 } 256 } 257 if (currentClass != null && u.equals(currentClass)) { 258 if (isAssignableFrom(t, currentSuperClass)) { 259 return true; 260 } 261 if (currentClassInterfaces != null) { 262 for (int i = 0; i < currentClassInterfaces.size(); ++i) { 263 Type v = (Type) currentClassInterfaces.get(i); 264 if (isAssignableFrom(t, v)) { 265 return true; 266 } 267 } 268 } 269 return false; 270 } 271 return getClass(t).isAssignableFrom(getClass(u)); 272 } 273 getClass(final Type t)274 protected Class getClass(final Type t) { 275 try { 276 if (t.getSort() == Type.ARRAY) { 277 return Class.forName(t.getDescriptor().replace('/', '.')); 278 } 279 return Class.forName(t.getClassName()); 280 } catch (ClassNotFoundException e) { 281 throw new RuntimeException(e.toString()); 282 } 283 } 284 } 285