1 17 package org.apache.bcel.verifier.structurals; 18 19 import java.io.PrintWriter ; 20 import java.io.StringWriter ; 21 import java.util.ArrayList ; 22 import java.util.Random ; 23 import java.util.Vector ; 24 import org.apache.bcel.Constants; 25 import org.apache.bcel.classfile.JavaClass; 26 import org.apache.bcel.classfile.Method; 27 import org.apache.bcel.generic.ConstantPoolGen; 28 import org.apache.bcel.generic.JsrInstruction; 29 import org.apache.bcel.generic.MethodGen; 30 import org.apache.bcel.generic.ObjectType; 31 import org.apache.bcel.generic.RET; 32 import org.apache.bcel.generic.ReturnaddressType; 33 import org.apache.bcel.generic.Type; 34 import org.apache.bcel.verifier.VerificationResult; 35 import org.apache.bcel.verifier.exc.AssertionViolatedException; 36 import org.apache.bcel.verifier.exc.VerifierConstraintViolatedException; 37 import org.apache.bcel.verifier.structurals.ControlFlowGraph; 38 import org.apache.bcel.verifier.structurals.ExceptionHandler; 39 import org.apache.bcel.verifier.structurals.ExecutionVisitor; 40 import org.apache.bcel.verifier.structurals.Frame; 41 import org.apache.bcel.verifier.structurals.InstConstraintVisitor; 42 import org.apache.bcel.verifier.structurals.InstructionContext; 43 import org.apache.bcel.verifier.structurals.OperandStack; 44 import org.apache.bcel.verifier.structurals.UninitializedObjectType; 45 46 57 58 public final class ModifiedPass3bVerifier { 59 64 65 76 private static final class InstructionContextQueue { 77 private final Vector ics = new Vector (); private final Vector ecs = new Vector (); 80 82 public void add( 83 final InstructionContext ic, 84 final ArrayList executionChain) 85 { 86 ics.add(ic); 87 ecs.add(executionChain); 88 } 89 90 public boolean isEmpty() { 91 return ics.isEmpty(); 92 } 93 94 public void remove() { 95 this.remove(0); 96 } 97 98 public void remove(final int i) { 99 ics.remove(i); 100 ecs.remove(i); 101 } 102 103 public InstructionContext getIC(final int i) { 104 return (InstructionContext) ics.get(i); 105 } 106 107 public ArrayList getEC(final int i) { 108 return (ArrayList ) ecs.get(i); 109 } 110 111 public int size() { 112 return ics.size(); 113 } 114 } 116 117 private static final boolean DEBUG = true; 118 119 120 private JavaClass jc; 121 122 123 private int method_no; 124 125 133 public ModifiedPass3bVerifier(final JavaClass jc, final int method_no) { 134 this.jc = jc; 135 this.method_no = method_no; 136 } 137 138 150 private void circulationPump( 151 final ControlFlowGraph cfg, 152 final InstructionContext start, 153 final Frame vanillaFrame, 154 final InstConstraintVisitor icv, 155 final ExecutionVisitor ev) 156 { 157 final Random random = new Random (); 158 InstructionContextQueue icq = new InstructionContextQueue(); 159 160 start.execute(vanillaFrame, new ArrayList (), icv, ev); icq.add(start, new ArrayList ()); 168 169 while (!icq.isEmpty()) { 171 InstructionContext u; 172 ArrayList ec; 173 if (!DEBUG) { 174 int r = random.nextInt(icq.size()); 175 u = icq.getIC(r); 176 ec = icq.getEC(r); 177 icq.remove(r); 178 } else { 179 u = icq.getIC(0); 180 ec = icq.getEC(0); 181 icq.remove(0); 182 } 183 184 ArrayList oldchain = (ArrayList ) ec.clone(); 185 ArrayList newchain = (ArrayList ) ec.clone(); 186 newchain.add(u); 187 188 if (u.getInstruction().getInstruction() instanceof RET) { 189 RET ret = (RET) u.getInstruction().getInstruction(); 193 ReturnaddressType t = (ReturnaddressType) u.getOutFrame(oldchain) 194 .getLocals() 195 .get(ret.getIndex()); 196 InstructionContext theSuccessor = cfg.contextOf(t.getTarget()); 197 198 InstructionContext lastJSR = null; 200 int skip_jsr = 0; 201 for (int ss = oldchain.size() - 1; ss >= 0; ss--) { 202 if (skip_jsr < 0) { 203 throw new AssertionViolatedException("More RET than JSR in execution chain?!"); 204 } 205 if (((InstructionContext) oldchain.get(ss)).getInstruction() 207 .getInstruction() instanceof JsrInstruction) 208 { 209 if (skip_jsr == 0) { 210 lastJSR = (InstructionContext) oldchain.get(ss); 211 break; 212 } else { 213 skip_jsr--; 214 } 215 } 216 if (((InstructionContext) oldchain.get(ss)).getInstruction() 217 .getInstruction() instanceof RET) 218 { 219 skip_jsr++; 220 } 221 } 222 if (lastJSR == null) { 223 throw new AssertionViolatedException("RET without a JSR before in ExecutionChain?! EC: '" 224 + oldchain + "'."); 225 } 226 JsrInstruction jsr = (JsrInstruction) lastJSR.getInstruction() 227 .getInstruction(); 228 if (theSuccessor != cfg.contextOf(jsr.physicalSuccessor())) { 229 throw new AssertionViolatedException("RET '" 230 + u.getInstruction() 231 + "' info inconsistent: jump back to '" 232 + theSuccessor + "' or '" 233 + cfg.contextOf(jsr.physicalSuccessor()) + "'?"); 234 } 235 236 if (theSuccessor.execute(u.getOutFrame(oldchain), 237 newchain, 238 icv, 239 ev)) 240 { 241 icq.add(theSuccessor, (ArrayList ) newchain.clone()); 242 } 243 } else { 245 InstructionContext[] succs = u.getSuccessors(); 247 for (int s = 0; s < succs.length; s++) { 248 InstructionContext v = succs[s]; 249 if (v.execute(u.getOutFrame(oldchain), newchain, icv, ev)) { 250 icq.add(v, (ArrayList ) newchain.clone()); 251 } 252 } 253 } 255 ExceptionHandler[] exc_hds = u.getExceptionHandlers(); 258 for (int s = 0; s < exc_hds.length; s++) { 259 InstructionContext v = cfg.contextOf(exc_hds[s].getHandlerStart()); 260 if (v.execute(new Frame(u.getOutFrame(oldchain).getLocals(), 279 new OperandStack(u.getOutFrame(oldchain) 280 .getStack() 281 .maxStack(), 282 (exc_hds[s].getExceptionType() == null 283 ? Type.THROWABLE 284 : exc_hds[s].getExceptionType()))), 285 new ArrayList (), 286 icv, 287 ev)) 288 { 289 icq.add(v, new ArrayList ()); 290 } 291 } 292 293 } 295 321 } 322 323 335 public VerificationResult do_verify() { 336 ConstantPoolGen constantPoolGen = new ConstantPoolGen(jc.getConstantPool()); 337 InstConstraintVisitor icv = new InstConstraintVisitor(); 339 icv.setConstantPoolGen(constantPoolGen); 340 341 ExecutionVisitor ev = new ExecutionVisitor(); 342 ev.setConstantPoolGen(constantPoolGen); 343 344 Method[] methods = jc.getMethods(); 347 try { 348 349 MethodGen mg = new MethodGen(methods[method_no], 350 jc.getClassName(), 351 constantPoolGen); 352 353 icv.setMethodGen(mg); 354 355 if (!(mg.isAbstract() || mg.isNative())) { 359 ControlFlowGraph cfg = new ControlFlowGraph(mg); 360 361 Frame f = new Frame(mg.getMaxLocals(), mg.getMaxStack()); 363 if (!mg.isStatic()) { 364 if (mg.getName().equals(Constants.CONSTRUCTOR_NAME)) { 365 Frame._this = new UninitializedObjectType(new ObjectType(jc.getClassName())); 366 f.getLocals().set(0, Frame._this); 367 } else { 368 Frame._this = null; 369 f.getLocals().set(0, new ObjectType(jc.getClassName())); 370 } 371 } 372 Type[] argtypes = mg.getArgumentTypes(); 373 int twoslotoffset = 0; 374 for (int j = 0; j < argtypes.length; j++) { 375 if (argtypes[j] == Type.SHORT || argtypes[j] == Type.BYTE 376 || argtypes[j] == Type.CHAR 377 || argtypes[j] == Type.BOOLEAN) 378 { 379 argtypes[j] = Type.INT; 380 } 381 f.getLocals().set(twoslotoffset + j 382 + (mg.isStatic() ? 0 : 1), 383 argtypes[j]); 384 if (argtypes[j].getSize() == 2) { 385 twoslotoffset++; 386 f.getLocals().set(twoslotoffset + j 387 + (mg.isStatic() ? 0 : 1), 388 Type.UNKNOWN); 389 } 390 } 391 circulationPump(cfg, cfg.contextOf(mg.getInstructionList() 392 .getStart()), f, icv, ev); 393 } 394 } catch (VerifierConstraintViolatedException ce) { 395 ce.extendMessage("Constraint violated in method '" 396 + methods[method_no] + "':\n", ""); 397 return new VerificationResult(VerificationResult.VERIFIED_REJECTED, 398 ce.getMessage()); 399 } catch (RuntimeException re) { 400 402 StringWriter sw = new StringWriter (); 403 PrintWriter pw = new PrintWriter (sw); 404 re.printStackTrace(pw); 405 406 throw new AssertionViolatedException("Some RuntimeException occured while verify()ing class '" 407 + jc.getClassName() 408 + "', method '" 409 + methods[method_no] 410 + "'. Original RuntimeException's stack trace:\n---\n" 411 + sw 412 + "---\n"); 413 } 414 return VerificationResult.VR_OK; 415 } 416 417 422 public int getMethodNo() { 423 return method_no; 424 } 425 } 426 | Popular Tags |