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.Type;
58  import org.apache.bcel.generic.ReferenceType;
59  import org.apache.bcel.verifier.exc.*;
60  
61  /***
62   * This class implements an array of local variables used for symbolic JVM
63   * simulation.
64   *
65   * @version $Id: LocalVariables.java,v 1.2 2002/08/02 11:57:51 enver Exp $
66   * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
67   */
68  public class LocalVariables{
69  	/*** The Type[] containing the local variable slots. */
70  	private Type[] locals;
71  
72  	/***
73  	 * Creates a new LocalVariables object.
74  	 */
75  	public LocalVariables(int maxLocals){
76  		locals = new Type[maxLocals];
77  		for (int i=0; i<maxLocals; i++){
78  			locals[i] = Type.UNKNOWN;
79  		}
80  	}
81  
82  	/***
83  	 * Returns a deep copy of this object; i.e. the clone
84  	 * operates on a new local variable array.
85  	 * However, the Type objects in the array are shared.
86  	 */
87  	protected Object clone(){
88  		LocalVariables lvs = new LocalVariables(locals.length);
89  		for (int i=0; i<locals.length; i++){
90  			lvs.locals[i] = this.locals[i];
91  		}
92  		return lvs;
93  	}
94  
95  	/***
96  	 * Returns the type of the local variable slot i.
97  	 */
98  	public Type get(int i){
99  		return locals[i];
100 	}
101 
102 	/***
103 	 * Returns a (correctly typed) clone of this object.
104 	 * This is equivalent to ((LocalVariables) this.clone()).
105 	 */
106 	public LocalVariables getClone(){
107 		return (LocalVariables) this.clone();
108 	}
109 
110 	/***
111 	 * Returns the number of local variable slots this
112 	 * LocalVariables instance has.
113 	 */
114 	public int maxLocals(){
115 		return locals.length;
116 	}
117 
118 	/***
119 	 * Sets a new Type for the given local variable slot.
120 	 */
121 	public void set(int i, Type type){
122 		if (type == Type.BYTE || type == Type.SHORT || type == Type.BOOLEAN || type == Type.CHAR){
123 			throw new AssertionViolatedException("LocalVariables do not know about '"+type+"'. Use Type.INT instead.");
124 		}
125 		locals[i] = type;
126 	}
127 
128 	/*
129 	 * Fulfills the general contract of Object.equals().
130 	 */
131 	public boolean equals(Object o){
132 		if (!(o instanceof LocalVariables)) return false;
133 		LocalVariables lv = (LocalVariables) o;
134 		if (this.locals.length != lv.locals.length) return false;
135 		for (int i=0; i<this.locals.length; i++){
136 			if (!this.locals[i].equals(lv.locals[i])){
137 				//System.out.println(this.locals[i]+" is not "+lv.locals[i]);
138 				return false;
139 			}
140 		}
141 		return true;
142 	}
143 	
144 	/***
145 	 * Merges two local variables sets as described in the Java Virtual Machine Specification,
146 	 * Second Edition, section 4.9.2, page 146.
147 	 */
148 	public void merge(LocalVariables lv){
149 
150 		if (this.locals.length != lv.locals.length){
151 			throw new AssertionViolatedException("Merging LocalVariables of different size?!? From different methods or what?!?");
152 		}
153 
154 		for (int i=0; i<locals.length; i++){
155 			merge(lv, i);
156 		}
157 	}
158 	
159 	/***
160 	 * Merges a single local variable.
161 	 *
162 	 * @see #merge(LocalVariables)
163 	 */
164 	private void merge(LocalVariables lv, int i){
165 		
166 		// We won't accept an unitialized object if we know it was initialized;
167 		// compare vmspec2, 4.9.4, last paragraph.
168 		if ( (!(locals[i] instanceof UninitializedObjectType)) && (lv.locals[i] instanceof UninitializedObjectType) ){
169 			throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
170 		}
171 		// Even harder, what about _different_ uninitialized object types?!
172 		if ( (!(locals[i].equals(lv.locals[i]))) && (locals[i] instanceof UninitializedObjectType) && (lv.locals[i] instanceof UninitializedObjectType) ){
173 			throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
174 		}
175 		// If we just didn't know that it was initialized, we have now learned.
176 		if (locals[i] instanceof UninitializedObjectType){
177 			if (! (lv.locals[i] instanceof UninitializedObjectType)){
178 				locals[i] = ((UninitializedObjectType) locals[i]).getInitialized();
179 			}
180 		}
181 		if ((locals[i] instanceof ReferenceType) && (lv.locals[i] instanceof ReferenceType)){
182 			if (! locals[i].equals(lv.locals[i])){ // needed in case of two UninitializedObjectType instances
183 				Type sup = ((ReferenceType) locals[i]).getFirstCommonSuperclass((ReferenceType) (lv.locals[i]));
184 
185 				if (sup != null){
186 					locals[i] = sup;
187 				}
188 				else{
189 					// We should have checked this in Pass2!
190 					throw new AssertionViolatedException("Could not load all the super classes of '"+locals[i]+"' and '"+lv.locals[i]+"'.");
191 				}
192 			}
193 		}
194 		else{
195 			if (! (locals[i].equals(lv.locals[i])) ){
196 /*TODO
197 				if ((locals[i] instanceof org.apache.bcel.generic.ReturnaddressType) && (lv.locals[i] instanceof org.apache.bcel.generic.ReturnaddressType)){
198 					//System.err.println("merging "+locals[i]+" and "+lv.locals[i]);
199 					throw new AssertionViolatedException("Merging different ReturnAddresses: '"+locals[i]+"' and '"+lv.locals[i]+"'.");
200 				}
201 */
202 				locals[i] = Type.UNKNOWN;
203 			}
204 		}
205 	}
206 
207 	/***
208 	 * Returns a String representation of this object.
209 	 */
210 	public String toString(){
211 		String s = new String();
212 		for (int i=0; i<locals.length; i++){
213 			s += Integer.toString(i)+": "+locals[i]+"\n";
214 		}
215 		return s;
216 	}
217 
218 	/***
219 	 * Replaces all occurences of u in this local variables set
220 	 * with an "initialized" ObjectType.
221 	 */
222 	public void initializeObject(UninitializedObjectType u){
223 		for (int i=0; i<locals.length; i++){
224 			if (locals[i] == u){
225 				locals[i] = u.getInitialized();
226 			}
227 		}
228 	}
229 }
This page was automatically generated by Maven