Example #1
0
 byte[] counterAdaptClass(final InputStream is, final String name) throws Exception {
   JavaClass jc = new ClassParser(is, name + ".class").parse();
   ClassGen cg = new ClassGen(jc);
   String cName = cg.getClassName();
   ConstantPoolGen cp = cg.getConstantPool();
   if (!cg.isInterface()) {
     FieldGen fg = new FieldGen(ACC_PUBLIC, Type.getType("I"), "_counter", cp);
     cg.addField(fg.getField());
   }
   Method[] ms = cg.getMethods();
   for (int j = 0; j < ms.length; ++j) {
     MethodGen mg = new MethodGen(ms[j], cg.getClassName(), cp);
     if (!mg.getName().equals("<init>") && !mg.isStatic() && !mg.isAbstract() && !mg.isNative()) {
       if (mg.getInstructionList() != null) {
         InstructionList il = new InstructionList();
         il.append(new ALOAD(0));
         il.append(new ALOAD(0));
         il.append(new GETFIELD(cp.addFieldref(name, "_counter", "I")));
         il.append(new ICONST(1));
         il.append(new IADD());
         il.append(new PUTFIELD(cp.addFieldref(name, "_counter", "I")));
         mg.getInstructionList().insert(il);
         mg.setMaxStack(Math.max(mg.getMaxStack(), 2));
         boolean lv = ms[j].getLocalVariableTable() == null;
         boolean ln = ms[j].getLineNumberTable() == null;
         if (lv) {
           mg.removeLocalVariables();
         }
         if (ln) {
           mg.removeLineNumbers();
         }
         cg.replaceMethod(ms[j], mg.getMethod());
       }
     }
   }
   return cg.getJavaClass().getBytes();
 }
  /**
   * Pass 3b implements the data flow analysis as described in the Java Virtual Machine
   * Specification, Second Edition. Later versions will use LocalVariablesInfo objects to verify if
   * the verifier-inferred types and the class file's debug information (LocalVariables attributes)
   * match [TODO].
   *
   * @see org.apache.bcel.verifier.statics.LocalVariablesInfo
   * @see org.apache.bcel.verifier.statics.Pass2Verifier#getLocalVariablesInfo(int)
   */
  @Override
  public VerificationResult do_verify() {
    if (!myOwner.doPass3a(method_no).equals(VerificationResult.VR_OK)) {
      return VerificationResult.VR_NOTYET;
    }

    // Pass 3a ran before, so it's safe to assume the JavaClass object is
    // in the BCEL repository.
    JavaClass jc;
    try {
      jc = Repository.lookupClass(myOwner.getClassName());
    } catch (ClassNotFoundException e) {
      // FIXME: maybe not the best way to handle this
      throw new AssertionViolatedException("Missing class: " + e, e);
    }

    ConstantPoolGen constantPoolGen = new ConstantPoolGen(jc.getConstantPool());
    // Init Visitors
    InstConstraintVisitor icv = new InstConstraintVisitor();
    icv.setConstantPoolGen(constantPoolGen);

    ExecutionVisitor ev = new ExecutionVisitor();
    ev.setConstantPoolGen(constantPoolGen);

    Method[] methods = jc.getMethods(); // Method no "method_no" exists, we ran Pass3a before on it!

    try {

      MethodGen mg = new MethodGen(methods[method_no], myOwner.getClassName(), constantPoolGen);

      icv.setMethodGen(mg);

      ////////////// DFA BEGINS HERE ////////////////
      if (!(mg.isAbstract() || mg.isNative())) { // IF mg HAS CODE (See pass 2)

        ControlFlowGraph cfg = new ControlFlowGraph(mg);

        // Build the initial frame situation for this method.
        Frame f = new Frame(mg.getMaxLocals(), mg.getMaxStack());
        if (!mg.isStatic()) {
          if (mg.getName().equals(Constants.CONSTRUCTOR_NAME)) {
            Frame._this = new UninitializedObjectType(ObjectType.getInstance(jc.getClassName()));
            f.getLocals().set(0, Frame._this);
          } else {
            Frame._this = null;
            f.getLocals().set(0, ObjectType.getInstance(jc.getClassName()));
          }
        }
        Type[] argtypes = mg.getArgumentTypes();
        int twoslotoffset = 0;
        for (int j = 0; j < argtypes.length; j++) {
          if (argtypes[j] == Type.SHORT
              || argtypes[j] == Type.BYTE
              || argtypes[j] == Type.CHAR
              || argtypes[j] == Type.BOOLEAN) {
            argtypes[j] = Type.INT;
          }
          f.getLocals().set(twoslotoffset + j + (mg.isStatic() ? 0 : 1), argtypes[j]);
          if (argtypes[j].getSize() == 2) {
            twoslotoffset++;
            f.getLocals().set(twoslotoffset + j + (mg.isStatic() ? 0 : 1), Type.UNKNOWN);
          }
        }
        circulationPump(mg, cfg, cfg.contextOf(mg.getInstructionList().getStart()), f, icv, ev);
      }
    } catch (VerifierConstraintViolatedException ce) {
      ce.extendMessage("Constraint violated in method '" + methods[method_no] + "':\n", "");
      return new VerificationResult(VerificationResult.VERIFIED_REJECTED, ce.getMessage());
    } catch (RuntimeException re) {
      // These are internal errors

      StringWriter sw = new StringWriter();
      PrintWriter pw = new PrintWriter(sw);
      re.printStackTrace(pw);

      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",
          re);
    }
    return VerificationResult.VR_OK;
  }