View Javadoc
1 package org.apache.bcel.verifier.structurals; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache BCEL" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache BCEL", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import org.apache.bcel.generic.*; 58 import org.apache.bcel.verifier.exc.*; 59 import java.util.*; 60 61 /*** 62 * This class implements a stack used for symbolic JVM stack simulation. 63 * [It's used an an operand stack substitute.] 64 * Elements of this stack are org.apache.bcel.generic.Type objects. 65 * 66 * @version $Id: OperandStack.java,v 1.2 2002/08/02 11:57:51 enver Exp $ 67 * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A> 68 */ 69 public class OperandStack{ 70 71 /*** We hold the stack information here. */ 72 private ArrayList stack = new ArrayList(); 73 74 /*** The maximum number of stack slots this OperandStack instance may hold. */ 75 private int maxStack; 76 77 /*** 78 * Creates an empty stack with a maximum of maxStack slots. 79 */ 80 public OperandStack(int maxStack){ 81 this.maxStack = maxStack; 82 } 83 84 /*** 85 * Creates an otherwise empty stack with a maximum of maxStack slots and 86 * the ObjectType 'obj' at the top. 87 */ 88 public OperandStack(int maxStack, ObjectType obj){ 89 this.maxStack = maxStack; 90 this.push(obj); 91 } 92 /*** 93 * Returns a deep copy of this object; that means, the clone operates 94 * on a new stack. However, the Type objects on the stack are 95 * shared. 96 */ 97 protected Object clone(){ 98 OperandStack newstack = new OperandStack(this.maxStack); 99 newstack.stack = (ArrayList) this.stack.clone(); 100 return newstack; 101 } 102 103 /*** 104 * Clears the stack. 105 */ 106 public void clear(){ 107 stack = new ArrayList(); 108 } 109 110 /*** 111 * Returns true if and only if this OperandStack 112 * equals another, meaning equal lengths and equal 113 * objects on the stacks. 114 */ 115 public boolean equals(Object o){ 116 if (!(o instanceof OperandStack)) return false; 117 OperandStack s = (OperandStack) o; 118 return this.stack.equals(s.stack); 119 } 120 121 /*** 122 * Returns a (typed!) clone of this. 123 * 124 * @see #clone() 125 */ 126 public OperandStack getClone(){ 127 return (OperandStack) this.clone(); 128 } 129 130 /*** 131 * Returns true IFF this OperandStack is empty. 132 */ 133 public boolean isEmpty(){ 134 return stack.isEmpty(); 135 } 136 137 /*** 138 * Returns the number of stack slots this stack can hold. 139 */ 140 public int maxStack(){ 141 return this.maxStack; 142 } 143 144 /*** 145 * Returns the element on top of the stack. The element is not popped off the stack! 146 */ 147 public Type peek(){ 148 return peek(0); 149 } 150 151 /*** 152 * Returns the element that's i elements below the top element; that means, 153 * iff i==0 the top element is returned. The element is not popped off the stack! 154 */ 155 public Type peek(int i){ 156 return (Type) stack.get(size()-i-1); 157 } 158 159 /*** 160 * Returns the element on top of the stack. The element is popped off the stack. 161 */ 162 public Type pop(){ 163 Type e = (Type) stack.remove(size()-1); 164 return e; 165 } 166 167 /*** 168 * Pops i elements off the stack. ALWAYS RETURNS "null"!!! 169 */ 170 public Type pop(int i){ 171 for (int j=0; j<i; j++){ 172 pop(); 173 } 174 return null; 175 } 176 177 /*** 178 * Pushes a Type object onto the stack. 179 */ 180 public void push(Type type){ 181 if (type == null) throw new AssertionViolatedException("Cannot push NULL onto OperandStack."); 182 if (type == Type.BOOLEAN || type == Type.CHAR || type == Type.BYTE || type == Type.SHORT){ 183 throw new AssertionViolatedException("The OperandStack does not know about '"+type+"'; use Type.INT instead."); 184 } 185 if (slotsUsed() >= maxStack){ 186 throw new AssertionViolatedException("OperandStack too small, should have thrown proper Exception elsewhere. Stack: "+this); 187 } 188 stack.add(type); 189 } 190 191 /*** 192 * Returns the size of this OperandStack; that means, how many Type objects there are. 193 */ 194 int size(){ 195 return stack.size(); 196 } 197 198 /*** 199 * Returns the number of stack slots used. 200 * @see #maxStack() 201 */ 202 public int slotsUsed(){ 203 /* XXX change this to a better implementation using a variable 204 that keeps track of the actual slotsUsed()-value monitoring 205 all push()es and pop()s. 206 */ 207 int slots = 0; 208 for (int i=0; i<stack.size(); i++){ 209 slots += peek(i).getSize(); 210 } 211 return slots; 212 } 213 214 /*** 215 * Returns a String representation of this OperandStack instance. 216 */ 217 public String toString(){ 218 String s = "Slots used: "+slotsUsed()+" MaxStack: "+maxStack+".\n"; 219 for (int i=0; i<size(); i++){ 220 s+=peek(i)+" (Size: "+peek(i).getSize()+")\n"; 221 } 222 return s; 223 } 224 225 /*** 226 * Merges another stack state into this instance's stack state. 227 * See the Java Virtual Machine Specification, Second Edition, page 146: 4.9.2 228 * for details. 229 */ 230 public void merge(OperandStack s){ 231 if ( (slotsUsed() != s.slotsUsed()) || (size() != s.size()) ) 232 throw new StructuralCodeConstraintException("Cannot merge stacks of different size:\nOperandStack A:\n"+this+"\nOperandStack B:\n"+s); 233 234 for (int i=0; i<size(); i++){ 235 // If the object _was_ initialized and we're supposed to merge 236 // in some uninitialized object, we reject the code (see vmspec2, 4.9.4, last paragraph). 237 if ( (! (stack.get(i) instanceof UninitializedObjectType)) && (s.stack.get(i) instanceof UninitializedObjectType) ){ 238 throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected."); 239 } 240 // Even harder, we're not initialized but are supposed to broaden 241 // the known object type 242 if ( (!(stack.get(i).equals(s.stack.get(i)))) && (stack.get(i) instanceof UninitializedObjectType) && (!(s.stack.get(i) instanceof UninitializedObjectType))){ 243 throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected."); 244 } 245 // on the other hand... 246 if (stack.get(i) instanceof UninitializedObjectType){ //if we have an uninitialized object here 247 if (! (s.stack.get(i) instanceof UninitializedObjectType)){ //that has been initialized by now 248 stack.set(i, ((UninitializedObjectType) (stack.get(i))).getInitialized() ); //note that. 249 } 250 } 251 if (! stack.get(i).equals(s.stack.get(i))){ 252 if ( (stack.get(i) instanceof ReferenceType) && 253 (s.stack.get(i) instanceof ReferenceType) ){ 254 stack.set(i, ((ReferenceType) stack.get(i)).getFirstCommonSuperclass((ReferenceType) (s.stack.get(i)))); 255 } 256 else{ 257 throw new StructuralCodeConstraintException("Cannot merge stacks of different types:\nStack A:\n"+this+"\nStack B:\n"+s); 258 } 259 } 260 } 261 } 262 263 /*** 264 * Replaces all occurences of u in this OperandStack instance 265 * with an "initialized" ObjectType. 266 */ 267 public void initializeObject(UninitializedObjectType u){ 268 for (int i=0; i<stack.size(); i++){ 269 if (stack.get(i) == u){ 270 stack.set(i, u.getInitialized()); 271 } 272 } 273 } 274 275 }

This page was automatically generated by Maven