1 package com.sun.org.apache.bcel.internal.verifier.structurals; 2 3 56 57 import java.io.*; 58 import java.util.ArrayList ; 59 import java.util.Iterator ; 60 import java.util.Random ; 61 import java.util.Vector ; 62 import com.sun.org.apache.bcel.internal.Constants; 63 import com.sun.org.apache.bcel.internal.Repository; 64 import com.sun.org.apache.bcel.internal.classfile.*; 65 import com.sun.org.apache.bcel.internal.generic.*; 66 import com.sun.org.apache.bcel.internal.verifier.*; 67 import com.sun.org.apache.bcel.internal.verifier.statics.*; 68 import com.sun.org.apache.bcel.internal.verifier.exc.*; 69 70 81 82 public final class Pass3bVerifier extends PassVerifier{ 83 86 87 100 private static final class InstructionContextQueue{ 101 private Vector ics = new Vector (); private Vector ecs = new Vector (); public void add(InstructionContext ic, ArrayList executionChain){ 104 ics.add(ic); 105 ecs.add(executionChain); 106 } 107 public boolean isEmpty(){ 108 return ics.isEmpty(); 109 } 110 public void remove(){ 111 this.remove(0); 112 } 113 public void remove(int i){ 114 ics.remove(i); 115 ecs.remove(i); 116 } 117 public InstructionContext getIC(int i){ 118 return (InstructionContext) ics.get(i); 119 } 120 public ArrayList getEC(int i){ 121 return (ArrayList ) ecs.get(i); 122 } 123 public int size(){ 124 return ics.size(); 125 } 126 } 128 129 private static final boolean DEBUG = true; 130 131 132 private Verifier myOwner; 133 134 135 private int method_no; 136 137 142 public Pass3bVerifier(Verifier owner, int method_no){ 143 myOwner = owner; 144 this.method_no = method_no; 145 } 146 147 154 private void circulationPump(ControlFlowGraph cfg, InstructionContext start, Frame vanillaFrame, InstConstraintVisitor icv, ExecutionVisitor ev){ 155 final Random random = new Random (); 156 InstructionContextQueue icq = new InstructionContextQueue(); 157 158 start.execute(vanillaFrame, new ArrayList (), icv, ev); icq.add(start, new ArrayList ()); 161 162 while (!icq.isEmpty()){ 164 InstructionContext u; 165 ArrayList ec; 166 if (!DEBUG){ 167 int r = random.nextInt(icq.size()); 168 u = icq.getIC(r); 169 ec = icq.getEC(r); 170 icq.remove(r); 171 } 172 else{ 173 u = icq.getIC(0); 174 ec = icq.getEC(0); 175 icq.remove(0); 176 } 177 178 ArrayList oldchain = (ArrayList ) (ec.clone()); 179 ArrayList newchain = (ArrayList ) (ec.clone()); 180 newchain.add(u); 181 182 if ((u.getInstruction().getInstruction()) instanceof RET){ 183 RET ret = (RET) (u.getInstruction().getInstruction()); 187 ReturnaddressType t = (ReturnaddressType) u.getOutFrame(oldchain).getLocals().get(ret.getIndex()); 188 InstructionContext theSuccessor = cfg.contextOf(t.getTarget()); 189 190 InstructionContext lastJSR = null; 192 int skip_jsr = 0; 193 for (int ss=oldchain.size()-1; ss >= 0; ss--){ 194 if (skip_jsr < 0){ 195 throw new AssertionViolatedException("More RET than JSR in execution chain?!"); 196 } 197 if (((InstructionContext) oldchain.get(ss)).getInstruction().getInstruction() instanceof JsrInstruction){ 199 if (skip_jsr == 0){ 200 lastJSR = (InstructionContext) oldchain.get(ss); 201 break; 202 } 203 else{ 204 skip_jsr--; 205 } 206 } 207 if (((InstructionContext) oldchain.get(ss)).getInstruction().getInstruction() instanceof RET){ 208 skip_jsr++; 209 } 210 } 211 if (lastJSR == null){ 212 throw new AssertionViolatedException("RET without a JSR before in ExecutionChain?! EC: '"+oldchain+"'."); 213 } 214 JsrInstruction jsr = (JsrInstruction) (lastJSR.getInstruction().getInstruction()); 215 if ( theSuccessor != (cfg.contextOf(jsr.physicalSuccessor())) ){ 216 throw new AssertionViolatedException("RET '"+u.getInstruction()+"' info inconsistent: jump back to '"+theSuccessor+"' or '"+cfg.contextOf(jsr.physicalSuccessor())+"'?"); 217 } 218 219 if (theSuccessor.execute(u.getOutFrame(oldchain), newchain, icv, ev)){ 220 icq.add(theSuccessor, (ArrayList ) newchain.clone()); 221 } 222 } 223 else{ 225 InstructionContext[] succs = u.getSuccessors(); 227 for (int s=0; s<succs.length; s++){ 228 InstructionContext v = succs[s]; 229 if (v.execute(u.getOutFrame(oldchain), newchain, icv, ev)){ 230 icq.add(v, (ArrayList ) newchain.clone()); 231 } 232 } 233 } 235 ExceptionHandler[] exc_hds = u.getExceptionHandlers(); 238 for (int s=0; s<exc_hds.length; s++){ 239 InstructionContext v = cfg.contextOf(exc_hds[s].getHandlerStart()); 240 if (v.execute(new Frame(u.getOutFrame(oldchain).getLocals(), new OperandStack (u.getOutFrame(oldchain).getStack().maxStack(), (exc_hds[s].getExceptionType()==null? Type.THROWABLE : exc_hds[s].getExceptionType())) ), new ArrayList (), icv, ev)){ 251 icq.add(v, new ArrayList ()); 252 } 253 } 254 255 } 257 InstructionHandle ih = start.getInstruction(); 258 do{ 259 if ((ih.getInstruction() instanceof ReturnInstruction) && (!(cfg.isDead(ih)))) { 260 InstructionContext ic = cfg.contextOf(ih); 261 Frame f = ic.getOutFrame(new ArrayList ()); LocalVariables lvs = f.getLocals(); 263 for (int i=0; i<lvs.maxLocals(); i++){ 264 if (lvs.get(i) instanceof UninitializedObjectType){ 265 this.addMessage("Warning: ReturnInstruction '"+ic+"' may leave method with an uninitialized object in the local variables array '"+lvs+"'."); 266 } 267 } 268 OperandStack os = f.getStack(); 269 for (int i=0; i<os.size(); i++){ 270 if (os.peek(i) instanceof UninitializedObjectType){ 271 this.addMessage("Warning: ReturnInstruction '"+ic+"' may leave method with an uninitialized object on the operand stack '"+os+"'."); 272 } 273 } 274 } 275 }while ((ih = ih.getNext()) != null); 276 277 } 278 279 289 public VerificationResult do_verify(){ 290 if (! myOwner.doPass3a(method_no).equals(VerificationResult.VR_OK)){ 291 return VerificationResult.VR_NOTYET; 292 } 293 294 JavaClass jc = Repository.lookupClass(myOwner.getClassName()); 297 298 ConstantPoolGen constantPoolGen = new ConstantPoolGen(jc.getConstantPool()); 299 InstConstraintVisitor icv = new InstConstraintVisitor(); 301 icv.setConstantPoolGen(constantPoolGen); 302 303 ExecutionVisitor ev = new ExecutionVisitor(); 304 ev.setConstantPoolGen(constantPoolGen); 305 306 Method[] methods = jc.getMethods(); 308 try{ 309 310 MethodGen mg = new MethodGen(methods[method_no], myOwner.getClassName(), constantPoolGen); 311 312 icv.setMethodGen(mg); 313 314 if (! (mg.isAbstract() || mg.isNative()) ){ 317 ControlFlowGraph cfg = new ControlFlowGraph(mg); 318 319 Frame f = new Frame(mg.getMaxLocals(),mg.getMaxStack()); 321 if ( !mg.isStatic() ){ 322 if (mg.getName().equals(Constants.CONSTRUCTOR_NAME)){ 323 f._this = new UninitializedObjectType(new ObjectType(jc.getClassName())); 324 f.getLocals().set(0, f._this); 325 } 326 else{ 327 f._this = null; 328 f.getLocals().set(0, new ObjectType(jc.getClassName())); 329 } 330 } 331 Type[] argtypes = mg.getArgumentTypes(); 332 int twoslotoffset = 0; 333 for (int j=0; j<argtypes.length; j++){ 334 if (argtypes[j] == Type.SHORT || argtypes[j] == Type.BYTE || argtypes[j] == Type.CHAR || argtypes[j] == Type.BOOLEAN){ 335 argtypes[j] = Type.INT; 336 } 337 f.getLocals().set(twoslotoffset + j + (mg.isStatic()?0:1), argtypes[j]); 338 if (argtypes[j].getSize() == 2){ 339 twoslotoffset++; 340 f.getLocals().set(twoslotoffset + j + (mg.isStatic()?0:1), Type.UNKNOWN); 341 } 342 } 343 circulationPump(cfg, cfg.contextOf(mg.getInstructionList().getStart()), f, icv, ev); 344 } 345 } 346 catch (VerifierConstraintViolatedException ce){ 347 ce.extendMessage("Constraint violated in method '"+methods[method_no]+"':\n",""); 348 return new VerificationResult(VerificationResult.VERIFIED_REJECTED, ce.getMessage()); 349 } 350 catch (RuntimeException re){ 351 353 StringWriter sw = new StringWriter(); 354 PrintWriter pw = new PrintWriter(sw); 355 re.printStackTrace(pw); 356 357 throw new AssertionViolatedException("Some RuntimeException occured while verify()ing class '"+jc.getClassName()+"', method '"+methods[method_no]+"'. Original RuntimeException's stack trace:\n---\n"+sw+"---\n"); 358 } 359 return VerificationResult.VR_OK; 360 } 361 362 363 public int getMethodNo(){ 364 return method_no; 365 } 366 } 367 | Popular Tags |