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