@Override
  public MethodGen analyseInternal(final MethodGen methodGen) {
    assert methodGen != null : "Parameter 'methodGen' of method 'analyseInternal' must not be null";

    if (!methodGen.getMethod().isAbstract() && null != methodGen.getInstructionList()) {
      final List<InstructionHandle> instnsHandleList =
          Arrays.asList(methodGen.getInstructionList().getInstructionHandles());
      instnsHandleList.forEach(t -> analyseAsVisiting(t, methodGen));
      return methodGen;
    }
    return null;
  }
  @Override
  public void visitClassContext(ClassContext classContext) {
    JavaClass javaClass = classContext.getJavaClass();

    Method[] methodList = javaClass.getMethods();

    for (Method m : methodList) {
      MethodGen methodGen = classContext.getMethodGen(m);

      if (DEBUG) {
        System.out.println(">>> Method: " + m.getName());
      }

      // To suspect that an invalid String representation is being build,
      // we identify the construction of a MessageDigest and
      // the use of a function that trim leading 0.
      boolean invokeMessageDigest = false;
      boolean invokeToHexString = false;

      ConstantPoolGen cpg = classContext.getConstantPoolGen();
      if (methodGen == null || methodGen.getInstructionList() == null) {
        continue; // No instruction .. nothing to do
      }
      for (Iterator itIns = methodGen.getInstructionList().iterator(); itIns.hasNext(); ) {
        Instruction inst = ((InstructionHandle) itIns.next()).getInstruction();
        if (DEBUG) {
          ByteCode.printOpCode(inst, cpg);
        }

        if (inst instanceof INVOKEVIRTUAL) { // MessageDigest.digest is called
          INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) inst;
          if ("java.security.MessageDigest".equals(invoke.getClassName(cpg))
              && "digest".equals(invoke.getMethodName(cpg))) {
            invokeMessageDigest = true;
          }
        } else if (inst instanceof INVOKESTATIC
            && invokeMessageDigest) { // The conversion must occurs after the digest was created
          INVOKESTATIC invoke = (INVOKESTATIC) inst;
          if ("java.lang.Integer".equals(invoke.getClassName(cpg))
              && "toHexString".equals(invoke.getMethodName(cpg))) {
            invokeToHexString = true;
          }
        }
      }

      if (invokeMessageDigest && invokeToHexString) {
        bugReporter.reportBug(
            new BugInstance(this, BAD_HEXA_CONVERSION_TYPE, Priorities.NORMAL_PRIORITY) //
                .addClassAndMethod(javaClass, m));
      }
    }
  }
  /**
   * Runs through specified class and find index of method specified by methodName. The index is
   * than used as key to obtain handlers. Note: Not the best solution
   *
   * @param fullyQualifiedClassName
   * @param methodName
   * @return
   */
  private InstructionList provideHandlersToMethod(
      String fullyQualifiedClassName, String methodName) {

    InstructionList handlers = null;
    try {
      JavaClass cl = Repository.lookupClass(fullyQualifiedClassName);
      ClassGen cg = new ClassGen(cl);
      Method[] methods = cg.getMethods();
      int methodIndex = 0;
      for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().equals(methodName)) {
          methodIndex = i;
        }
      }
      MethodGen mg = new MethodGen(cg.getMethodAt(methodIndex), null, cg.getConstantPool());
      handlers = mg.getInstructionList();

    } catch (ClassNotFoundException ex) {
      Logger.getLogger(BugPatternDetectorImpl.class.getName())
          .log(
              Level.SEVERE,
              "The method "
                  + methodName
                  + " was not found in "
                  + fullyQualifiedClassName
                  + " class.");
    }
    return handlers;
  }
Beispiel #4
0
  CFG createCFG(String className) throws ClassNotFoundException {
    CFG cfg = new CFG();
    JavaClass jc = Repository.lookupClass(className);
    ClassGen cg = new ClassGen(jc);
    ConstantPoolGen cpg = cg.getConstantPool();
    for (Method m : cg.getMethods()) {
      MethodGen mg = new MethodGen(m, cg.getClassName(), cpg);
      InstructionList il = mg.getInstructionList();
      InstructionHandle[] handles = il.getInstructionHandles();
      int prev = 0;
      for (InstructionHandle ih : handles) {
        int position = ih.getPosition();
        cfg.addNode(position, m, jc);
        Instruction inst = ih.getInstruction();

        boolean br = inst.getName().contains("if") || inst.getName().contains("goto");
        boolean ret = inst.getName().contains("return");
        boolean stat = inst.getName().contains("invokestatic");
        int len = inst.getLength();

        if (stat) {
          int index = inst.toString(true).indexOf(" ");
          String name = inst.toString(true).substring(index + 1);
          int tar = Integer.valueOf(name);
          INVOKESTATIC inv = new INVOKESTATIC(tar);
          name = inv.getMethodName(cpg);

          Method m2 = null;
          Method[] tm = cg.getMethods();
          for (int i = 0; i < tm.length; i++) {
            if (tm[i].getName().equals(name)) {
              m2 = tm[i];
            }
          }
          cfg.addEdge(position, m, jc, 0, m2, jc);
          cfg.addEdge(-1, m2, jc, position + len, m, jc);
        }

        if (!ret && !stat) {
          cfg.addEdge(position, position + len, m, jc);
        }
        if (br) {
          cfg.addEdge(position, position + len, m, jc);
          IF_ICMPGE comp = new IF_ICMPGE(ih);
          String name = comp.getTarget().toString(false);
          int index = name.indexOf(">");
          name = name.substring(index + 2);
          int tar = Integer.valueOf(name);
          cfg.addEdge(position, tar, m, jc);
        }
        if (ret) {
          cfg.addEdge(position, -1, m, jc);
        }

        prev = position;
      }
      System.out.println(cfg.toString());
    }
    return cfg;
  }
Beispiel #5
0
 byte[] nullAdaptClass(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();
   Method[] ms = cg.getMethods();
   for (int j = 0; j < ms.length; ++j) {
     MethodGen mg = new MethodGen(ms[j], cg.getClassName(), cp);
     boolean lv = ms[j].getLocalVariableTable() == null;
     boolean ln = ms[j].getLineNumberTable() == null;
     if (lv) {
       mg.removeLocalVariables();
     }
     if (ln) {
       mg.removeLineNumbers();
     }
     mg.stripAttributes(skipDebug);
     InstructionList il = mg.getInstructionList();
     if (il != null) {
       InstructionHandle ih = il.getStart();
       while (ih != null) {
         ih = ih.getNext();
       }
       if (compute) {
         mg.setMaxStack();
         mg.setMaxLocals();
       }
     }
     cg.replaceMethod(ms[j], mg.getMethod());
   }
   return cg.getJavaClass().getBytes();
 }
  /** Checks the specific method for consistency. */
  public static void checkMgen(MethodGen mgen) {

    if (skip_checks) return;

    try {
      mgen.toString();
      mgen.getLineNumberTable(mgen.getConstantPool());

      InstructionList ilist = mgen.getInstructionList();
      if (ilist == null || ilist.getStart() == null) return;
      CodeExceptionGen[] exceptionHandlers = mgen.getExceptionHandlers();
      for (CodeExceptionGen gen : exceptionHandlers) {
        assert ilist.contains(gen.getStartPC())
            : "exception handler "
                + gen
                + " has been forgotten in "
                + mgen.getClassName()
                + "."
                + mgen.getName();
      }
      MethodGen nmg = new MethodGen(mgen.getMethod(), mgen.getClassName(), mgen.getConstantPool());
      nmg.getLineNumberTable(mgen.getConstantPool());
    } catch (Throwable t) {
      System.out.printf("failure in method %s.%s\n", mgen.getClassName(), mgen.getName());
      t.printStackTrace();
      throw new Error(t);
    }
  }
 public SearchResult run(RSClient data, HashMap<String, ClassGen> classes) {
   for (ClassGen c : classes.values()) {
     ConstantPoolGen cpg = c.getConstantPool();
     if (cpg.lookupFloat(16384.0000f) != -1) {
       for (Method m : c.getMethods()) {
         if (m.isStatic()) {
           MethodGen gen = new MethodGen(m, c.getClassName(), cpg);
           InstructionList il = gen.getInstructionList();
           if (il == null) continue;
           InstructionFinder f = new InstructionFinder(il);
           Iterator e = f.search("GETSTATIC LDC FSUB PUTSTATIC");
           if (e.hasNext()) {
             InstructionHandle[] handles = (InstructionHandle[]) e.next();
             data.addField(
                 "MapAngle",
                 ((GETSTATIC) handles[0].getInstruction()).getClassName(cpg)
                     + "."
                     + ((GETSTATIC) handles[0].getInstruction()).getFieldName(cpg));
             return SearchResult.Success;
           }
         }
       }
     }
   }
   return SearchResult.Failure;
 }
Beispiel #8
0
  /** Instrument the specified method to replace mapped calls. */
  public void instrument_method(Method m, MethodGen mg) {

    // Loop through each instruction, making substitutions
    InstructionList il = mg.getInstructionList();
    for (InstructionHandle ih = il.getStart(); ih != null; ) {
      if (debug_instrument_inst.enabled()) {
        debug_instrument_inst.log("instrumenting instruction %s%n", ih);
        // ih.getInstruction().toString(pool.getConstantPool()));
      }
      InstructionList new_il = null;

      // Remember the next instruction to process
      InstructionHandle next_ih = ih.getNext();

      // Get the translation for this instruction (if any)
      new_il = xform_inst(mg, ih.getInstruction());
      if (debug_instrument_inst.enabled()) debug_instrument_inst.log("  new inst: %s%n", new_il);

      // If this instruction was modified, replace it with the new
      // instruction list. If this instruction was the target of any
      // jumps or line numbers , replace them with the first
      // instruction in the new list
      replace_instructions(il, ih, new_il);

      ih = next_ih;
    }
  }
 /**
  * TODO
  *
  * @param mg
  */
 public StackTypes(MethodGen mg) {
   InstructionList il = mg.getInstructionList();
   int size = 0;
   if (il != null) size = il.getEnd().getPosition();
   os_arr = new OperandStack[size + 1];
   if (track_locals) loc_arr = new LocalVariables[size + 1];
 }
Beispiel #10
0
  /** Start the method's visit. */
  public void start() {
    if (!mg.isAbstract() && !mg.isNative()) {
      for (InstructionHandle ih = mg.getInstructionList().getStart();
          ih != null;
          ih = ih.getNext()) {
        Instruction i = ih.getInstruction();

        if (!visitInstruction(i)) i.accept(this);
      }
      updateExceptionHandlers();
    }
  }
  /**
   * Transforms the init method to create the newly added join point member field.
   *
   * @param cp the ConstantPoolGen
   * @param cg the ClassGen
   * @param init the constructor for the class
   * @param method the current method
   * @param factory the objectfactory
   * @param methodSequence the methods sequence number
   * @return the modified constructor
   */
  private MethodGen createJoinPointField(
      final ConstantPoolGen cp,
      final ClassGen cg,
      final Method init,
      final Method method,
      final InstructionFactory factory,
      final int methodSequence) {

    final MethodGen mg = new MethodGen(init, cg.getClassName(), cp);
    final InstructionList il = mg.getInstructionList();
    final InstructionHandle[] ihs = il.getInstructionHandles();

    // grab the handle to the the return instruction of the constructor
    InstructionHandle ih = ihs[0];
    for (int i = 0; i < ihs.length; i++) {
      Instruction instruction = ihs[i].getInstruction();
      if (instruction instanceof ReturnInstruction) {
        ih = ihs[i]; // set the instruction handle to the return instruction
        break;
      }
    }

    final String joinPoint = getJoinPointName(method, methodSequence);

    final InstructionHandle ihPost;
    ihPost = il.insert(ih, factory.createLoad(Type.OBJECT, 0));
    il.insert(ih, factory.createNew(TransformationUtil.THREAD_LOCAL_CLASS));

    il.insert(ih, InstructionConstants.DUP);

    il.insert(
        ih,
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "<init>",
            Type.VOID,
            new Type[] {},
            Constants.INVOKESPECIAL));

    il.insert(
        ih,
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint,
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.PUTFIELD));
    il.redirectBranches(ih, ihPost);

    mg.setMaxStack();
    mg.setMaxLocals();

    return mg;
  }
Beispiel #12
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();
 }
  /*
   * (non-Javadoc)
   *
   * @see
   * edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
   * .classfile.IAnalysisCache, java.lang.Object)
   */
  public LoadedFieldSet analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
      throws CheckedAnalysisException {
    MethodGen methodGen = getMethodGen(analysisCache, descriptor);
    if (methodGen == null) return null;
    InstructionList il = methodGen.getInstructionList();

    LoadedFieldSet loadedFieldSet = new LoadedFieldSet(methodGen);
    ConstantPoolGen cpg = getConstantPoolGen(analysisCache, descriptor.getClassDescriptor());

    for (InstructionHandle handle = il.getStart(); handle != null; handle = handle.getNext()) {
      Instruction ins = handle.getInstruction();
      short opcode = ins.getOpcode();
      try {
        if (opcode == Constants.INVOKESTATIC) {
          INVOKESTATIC inv = (INVOKESTATIC) ins;
          if (Hierarchy.isInnerClassAccess(inv, cpg)) {
            InnerClassAccess access = Hierarchy.getInnerClassAccess(inv, cpg);
            /*
             * if (access == null) {
             * System.out.println("Missing inner class access in " +
             * SignatureConverter.convertMethodSignature(methodGen)
             * + " at " + inv); }
             */
            if (access != null) {
              if (access.isLoad()) loadedFieldSet.addLoad(handle, access.getField());
              else loadedFieldSet.addStore(handle, access.getField());
            }
          }
        } else if (fieldInstructionOpcodeSet.get(opcode)) {
          boolean isLoad = (opcode == Constants.GETFIELD || opcode == Constants.GETSTATIC);
          XField field = Hierarchy.findXField((FieldInstruction) ins, cpg);
          if (field != null) {
            if (isLoad) loadedFieldSet.addLoad(handle, field);
            else loadedFieldSet.addStore(handle, field);
          }
        }
      } catch (ClassNotFoundException e) {
        AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportMissingClass(e);
      }
    }

    return loadedFieldSet;
  }
  /** Adds code in nl to start of method mg * */
  public static void add_to_start(MethodGen mg, InstructionList nl) {

    // Add the code before the first instruction
    InstructionList il = mg.getInstructionList();
    InstructionHandle old_start = il.getStart();
    InstructionHandle new_start = il.insert(nl);

    // Move any LineNumbers and local variable that currently point to
    // the first instruction to include the new instructions. Other
    // targeters (branches, exceptions) should not include the new
    // code
    if (old_start.hasTargeters()) {
      for (InstructionTargeter it : old_start.getTargeters()) {
        if ((it instanceof LineNumberGen) || (it instanceof LocalVariableGen))
          it.updateTarget(old_start, new_start);
      }
    }
    mg.setMaxStack();
    mg.setMaxLocals();
  }
 static void nullBCELAdapt(final byte[] b) throws IOException {
   JavaClass jc = new ClassParser(new ByteArrayInputStream(b), "class-name").parse();
   ClassGen cg = new ClassGen(jc);
   ConstantPoolGen cp = cg.getConstantPool();
   Method[] ms = cg.getMethods();
   for (int k = 0; k < ms.length; ++k) {
     MethodGen mg = new MethodGen(ms[k], cg.getClassName(), cp);
     boolean lv = ms[k].getLocalVariableTable() == null;
     boolean ln = ms[k].getLineNumberTable() == null;
     if (lv) {
       mg.removeLocalVariables();
     }
     if (ln) {
       mg.removeLineNumbers();
     }
     mg.stripAttributes(skipDebug);
     InstructionList il = mg.getInstructionList();
     if (il != null) {
       InstructionHandle ih = il.getStart();
       while (ih != null) {
         ih = ih.getNext();
       }
       if (compute) {
         mg.setMaxStack();
         mg.setMaxLocals();
       }
       if (computeFrames) {
         ModifiedPass3bVerifier verif;
         verif = new ModifiedPass3bVerifier(jc, k);
         verif.do_verify();
       }
     }
     cg.replaceMethod(ms[k], mg.getMethod());
   }
   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;
  }
Beispiel #17
0
  /**
   * Processes each method in cg replacing any specified calls with static user calls.
   *
   * @param fullClassName must be packageName.className
   */
  private boolean map_calls(ClassGen cg, String fullClassName, ClassLoader loader) {

    boolean transformed = false;

    try {
      pgen = cg.getConstantPool();

      // Loop through each method in the class
      Method[] methods = cg.getMethods();
      for (int i = 0; i < methods.length; i++) {
        MethodGen mg = new MethodGen(methods[i], cg.getClassName(), pgen);

        // Get the instruction list and skip methods with no instructions
        InstructionList il = mg.getInstructionList();
        if (il == null) continue;

        if (debug) out.format("Original code: %s%n", mg.getMethod().getCode());

        instrument_method(methods[i], mg);

        // Remove the Local variable type table attribute (if any).
        // Evidently, some changes we make require this to be updated, but
        // without BCEL support, that would be hard to do.  Just delete it
        // for now (since it is optional, and we are unlikely to be used by
        // a debugger)
        for (Attribute a : mg.getCodeAttributes()) {
          if (is_local_variable_type_table(a)) {
            mg.removeCodeAttribute(a);
          }
        }

        // Update the instruction list
        mg.setInstructionList(il);
        mg.update();

        // Update the max stack and Max Locals
        mg.setMaxLocals();
        mg.setMaxStack();
        mg.update();

        // Update the method in the class
        cg.replaceMethod(methods[i], mg.getMethod());
        if (debug) out.format("Modified code: %s%n", mg.getMethod().getCode());

        // verify the new method
        // StackVer stackver = new StackVer();
        // VerificationResult vr = stackver.do_stack_ver (mg);
        // log ("vr for method %s = %s%n", mg.getName(), vr);
        // if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
        //  System.out.printf ("Warning BCEL Verify failed for method %s: %s",
        //                     mg.getName(), vr);
        //  System.out.printf ("Code: %n%s%n", mg.getMethod().getCode());
        // System.exit(1);
        // }
      }

      cg.update();
    } catch (Exception e) {
      out.format("Unexpected exception encountered: " + e);
      e.printStackTrace();
    }

    return transformed;
  }
Beispiel #18
0
  /**
   * Adds all the constants found in the given class into the given ConstantSet, and returns it.
   *
   * @see #getConstants(String)
   */
  public static ConstantSet getConstants(String classname, ConstantSet result) {

    ClassParser cp;
    JavaClass jc;
    try {
      String classfileBase = classname.replace('.', '/');
      InputStream is = ClassPath.SYSTEM_CLASS_PATH.getInputStream(classfileBase, ".class");
      cp = new ClassParser(is, classname);
      jc = cp.parse();
    } catch (java.io.IOException e) {
      throw new Error("IOException while reading '" + classname + "': " + e.getMessage());
    }
    result.classname = jc.getClassName();

    // Get all of the constants from the pool
    ConstantPool constant_pool = jc.getConstantPool();
    for (Constant c : constant_pool.getConstantPool()) {
      // System.out.printf ("*Constant = %s%n", c);
      if (c == null
          || c instanceof ConstantClass
          || c instanceof ConstantFieldref
          || c instanceof ConstantInterfaceMethodref
          || c instanceof ConstantMethodref
          || c instanceof ConstantNameAndType
          || c instanceof ConstantUtf8) {
        continue;
      }
      if (c instanceof ConstantString) {
        result.strings.add((String) ((ConstantString) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantDouble) {
        result.doubles.add((Double) ((ConstantDouble) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantFloat) {
        result.floats.add((Float) ((ConstantFloat) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantInteger) {
        result.ints.add((Integer) ((ConstantInteger) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantLong) {
        result.longs.add((Long) ((ConstantLong) c).getConstantValue(constant_pool));
      } else {
        throw new RuntimeException("Unrecognized constant of type " + c.getClass() + ": " + c);
      }
    }

    ClassGen gen = new ClassGen(jc);
    ConstantPoolGen pool = gen.getConstantPool();

    // Process the code in each method looking for literals
    for (Method m : jc.getMethods()) {
      MethodGen mg = new MethodGen(m, jc.getClassName(), pool);
      InstructionList il = mg.getInstructionList();
      if (il == null) {
        // System.out.println("No instructions for " + mg);
      } else {
        for (Instruction inst : il.getInstructions()) {
          switch (inst.getOpcode()) {

              // Compare two objects, no literals
            case Constants.IF_ACMPEQ:
            case Constants.IF_ACMPNE:
              break;

              // These instructions compare the integer on the top of the stack
              // to zero.  There are no literals here (except 0)
            case Constants.IFEQ:
            case Constants.IFNE:
            case Constants.IFLT:
            case Constants.IFGE:
            case Constants.IFGT:
            case Constants.IFLE:
              {
                break;
              }

              // Instanceof pushes either 0 or 1 on the stack depending on whether
              // the object on top of stack is of the specified type.
              // If were interested in class literals, this would be interesting
            case Constants.INSTANCEOF:
              break;

              // Duplicates the item on the top of stack.  No literal.
            case Constants.DUP:
              {
                break;
              }

              // Duplicates the item on the top of the stack and inserts it 2
              // values down in the stack.  No literals
            case Constants.DUP_X1:
              {
                break;
              }

              // Duplicates either the top 2 category 1 values or a single
              // category 2 value and inserts it 2 or 3 values down on the
              // stack.
            case Constants.DUP2_X1:
              {
                break;
              }

              // Duplicate either one category 2 value or two category 1 values.
            case Constants.DUP2:
              {
                break;
              }

              // Dup the category 1 value on the top of the stack and insert it either
              // two or three values down on the stack.
            case Constants.DUP_X2:
              {
                break;
              }

            case Constants.DUP2_X2:
              {
                break;
              }

              // Pop instructions discard the top of the stack.
            case Constants.POP:
              {
                break;
              }

              // Pops either the top 2 category 1 values or a single category 2 value
              // from the top of the stack.
            case Constants.POP2:
              {
                break;
              }

              // Swaps the two category 1 types on the top of the stack.
            case Constants.SWAP:
              {
                break;
              }

              // Compares two integers on the stack
            case Constants.IF_ICMPEQ:
            case Constants.IF_ICMPGE:
            case Constants.IF_ICMPGT:
            case Constants.IF_ICMPLE:
            case Constants.IF_ICMPLT:
            case Constants.IF_ICMPNE:
              {
                break;
              }

              // Get the value of a field
            case Constants.GETFIELD:
              {
                break;
              }

              // stores the top of stack into a field
            case Constants.PUTFIELD:
              {
                break;
              }

              // Pushes the value of a static field on the stack
            case Constants.GETSTATIC:
              {
                break;
              }

              // Pops a value off of the stack into a static field
            case Constants.PUTSTATIC:
              {
                break;
              }

              // pushes a local onto the stack
            case Constants.DLOAD:
            case Constants.DLOAD_0:
            case Constants.DLOAD_1:
            case Constants.DLOAD_2:
            case Constants.DLOAD_3:
            case Constants.FLOAD:
            case Constants.FLOAD_0:
            case Constants.FLOAD_1:
            case Constants.FLOAD_2:
            case Constants.FLOAD_3:
            case Constants.ILOAD:
            case Constants.ILOAD_0:
            case Constants.ILOAD_1:
            case Constants.ILOAD_2:
            case Constants.ILOAD_3:
            case Constants.LLOAD:
            case Constants.LLOAD_0:
            case Constants.LLOAD_1:
            case Constants.LLOAD_2:
            case Constants.LLOAD_3:
              {
                break;
              }

              // Pops a value off of the stack into a local
            case Constants.DSTORE:
            case Constants.DSTORE_0:
            case Constants.DSTORE_1:
            case Constants.DSTORE_2:
            case Constants.DSTORE_3:
            case Constants.FSTORE:
            case Constants.FSTORE_0:
            case Constants.FSTORE_1:
            case Constants.FSTORE_2:
            case Constants.FSTORE_3:
            case Constants.ISTORE:
            case Constants.ISTORE_0:
            case Constants.ISTORE_1:
            case Constants.ISTORE_2:
            case Constants.ISTORE_3:
            case Constants.LSTORE:
            case Constants.LSTORE_0:
            case Constants.LSTORE_1:
            case Constants.LSTORE_2:
            case Constants.LSTORE_3:
              {
                break;
              }

              // Push a value from the runtime constant pool.  We'll get these
              // values when processing the constant pool itself
            case Constants.LDC:
            case Constants.LDC_W:
            case Constants.LDC2_W:
              {
                break;
              }

              // Push the length of an array on the stack
            case Constants.ARRAYLENGTH:
              {
                break;
              }

              // Push small constants (-1..5) on the stack.  These literals are
              // too common to bother mentioning
            case Constants.DCONST_0:
            case Constants.DCONST_1:
            case Constants.FCONST_0:
            case Constants.FCONST_1:
            case Constants.FCONST_2:
            case Constants.ICONST_0:
            case Constants.ICONST_1:
            case Constants.ICONST_2:
            case Constants.ICONST_3:
            case Constants.ICONST_4:
            case Constants.ICONST_5:
            case Constants.ICONST_M1:
            case Constants.LCONST_0:
            case Constants.LCONST_1:
              {
                break;
              }

            case Constants.BIPUSH:
            case Constants.SIPUSH:
              {
                ConstantPushInstruction cpi = (ConstantPushInstruction) inst;
                result.ints.add((Integer) cpi.getValue());
                break;
              }

              // Primitive Binary operators.
            case Constants.DADD:
            case Constants.DCMPG:
            case Constants.DCMPL:
            case Constants.DDIV:
            case Constants.DMUL:
            case Constants.DREM:
            case Constants.DSUB:
            case Constants.FADD:
            case Constants.FCMPG:
            case Constants.FCMPL:
            case Constants.FDIV:
            case Constants.FMUL:
            case Constants.FREM:
            case Constants.FSUB:
            case Constants.IADD:
            case Constants.IAND:
            case Constants.IDIV:
            case Constants.IMUL:
            case Constants.IOR:
            case Constants.IREM:
            case Constants.ISHL:
            case Constants.ISHR:
            case Constants.ISUB:
            case Constants.IUSHR:
            case Constants.IXOR:
            case Constants.LADD:
            case Constants.LAND:
            case Constants.LCMP:
            case Constants.LDIV:
            case Constants.LMUL:
            case Constants.LOR:
            case Constants.LREM:
            case Constants.LSHL:
            case Constants.LSHR:
            case Constants.LSUB:
            case Constants.LUSHR:
            case Constants.LXOR:
              break;

            case Constants.LOOKUPSWITCH:
            case Constants.TABLESWITCH:
              break;

            case Constants.ANEWARRAY:
            case Constants.NEWARRAY:
              {
                break;
              }

            case Constants.MULTIANEWARRAY:
              {
                break;
              }

              // push the value at an index in an array
            case Constants.AALOAD:
            case Constants.BALOAD:
            case Constants.CALOAD:
            case Constants.DALOAD:
            case Constants.FALOAD:
            case Constants.IALOAD:
            case Constants.LALOAD:
            case Constants.SALOAD:
              {
                break;
              }

              // Pop the top of stack into an array location
            case Constants.AASTORE:
            case Constants.BASTORE:
            case Constants.CASTORE:
            case Constants.DASTORE:
            case Constants.FASTORE:
            case Constants.IASTORE:
            case Constants.LASTORE:
            case Constants.SASTORE:
              break;

            case Constants.ARETURN:
            case Constants.DRETURN:
            case Constants.FRETURN:
            case Constants.IRETURN:
            case Constants.LRETURN:
            case Constants.RETURN:
              {
                break;
              }

              // subroutine calls.
            case Constants.INVOKESTATIC:
            case Constants.INVOKEVIRTUAL:
            case Constants.INVOKESPECIAL:
            case Constants.INVOKEINTERFACE:
              break;

              // Throws an exception.
            case Constants.ATHROW:
              break;

              // Opcodes that don't need any modifications.  Here for reference
            case Constants.ACONST_NULL:
            case Constants.ALOAD:
            case Constants.ALOAD_0:
            case Constants.ALOAD_1:
            case Constants.ALOAD_2:
            case Constants.ALOAD_3:
            case Constants.ASTORE:
            case Constants.ASTORE_0:
            case Constants.ASTORE_1:
            case Constants.ASTORE_2:
            case Constants.ASTORE_3:
            case Constants.CHECKCAST:
            case Constants.D2F: // double to float
            case Constants.D2I: // double to integer
            case Constants.D2L: // double to long
            case Constants.DNEG: // Negate double on top of stack
            case Constants.F2D: // float to double
            case Constants.F2I: // float to integer
            case Constants.F2L: // float to long
            case Constants.FNEG: // Negate float on top of stack
            case Constants.GOTO:
            case Constants.GOTO_W:
            case Constants.I2B: // integer to byte
            case Constants.I2C: // integer to char
            case Constants.I2D: // integer to double
            case Constants.I2F: // integer to float
            case Constants.I2L: // integer to long
            case Constants.I2S: // integer to short
            case Constants.IFNONNULL:
            case Constants.IFNULL:
            case Constants.IINC: // increment local variable by a constant
            case Constants.INEG: // negate integer on top of stack
            case Constants.JSR: // pushes return address on the stack,
            case Constants.JSR_W:
            case Constants.L2D: // long to double
            case Constants.L2F: // long to float
            case Constants.L2I: // long to int
            case Constants.LNEG: // negate long on top of stack
            case Constants.MONITORENTER:
            case Constants.MONITOREXIT:
            case Constants.NEW:
            case Constants.NOP:
            case Constants.RET: // this is the internal JSR return
              break;

              // Make sure we didn't miss anything
            default:
              throw new Error("instruction " + inst + " unsupported");
          }
        }
      }
    }
    return result;
  }
Beispiel #19
0
  /**
   * Constructor.
   *
   * @param il A MethodGen object representing method to create the Subroutine objects of.
   */
  public Subroutines(MethodGen mg) {

    InstructionHandle[] all = mg.getInstructionList().getInstructionHandles();
    CodeExceptionGen[] handlers = mg.getExceptionHandlers();

    // Define our "Toplevel" fake subroutine.
    TOPLEVEL = new SubroutineImpl();

    // Calculate "real" subroutines.
    HashSet<InstructionHandle> sub_leaders =
        new HashSet<InstructionHandle>(); // Elements: InstructionHandle
    for (int i = 0; i < all.length; i++) {
      Instruction inst = all[i].getInstruction();
      if (inst instanceof JsrInstruction) {
        sub_leaders.add(((JsrInstruction) inst).getTarget());
      }
    }

    // Build up the database.
    Iterator iter = sub_leaders.iterator();
    while (iter.hasNext()) {
      SubroutineImpl sr = new SubroutineImpl();
      InstructionHandle astore = (InstructionHandle) (iter.next());
      sr.setLocalVariable(((ASTORE) (astore.getInstruction())).getIndex());
      subroutines.put(astore, sr);
    }

    // Fake it a bit. We want a virtual "TopLevel" subroutine.
    subroutines.put(all[0], TOPLEVEL);
    sub_leaders.add(all[0]);

    // Tell the subroutines about their JsrInstructions.
    // Note that there cannot be a JSR targeting the top-level
    // since "Jsr 0" is disallowed in Pass 3a.
    // Instructions shared by a subroutine and the toplevel are
    // disallowed and checked below, after the BFS.
    for (int i = 0; i < all.length; i++) {
      Instruction inst = all[i].getInstruction();
      if (inst instanceof JsrInstruction) {
        InstructionHandle leader = ((JsrInstruction) inst).getTarget();
        ((SubroutineImpl) getSubroutine(leader)).addEnteringJsrInstruction(all[i]);
      }
    }

    // Now do a BFS from every subroutine leader to find all the
    // instructions that belong to a subroutine.
    HashSet<InstructionHandle> instructions_assigned =
        new HashSet<InstructionHandle>(); // we don't want to assign an instruction to two or more
    // Subroutine objects.

    Hashtable<InstructionHandle, Color> colors =
        new Hashtable<
            InstructionHandle,
            Color>(); // Graph colouring. Key: InstructionHandle, Value: java.awt.Color .

    iter = sub_leaders.iterator();
    while (iter.hasNext()) {
      // Do some BFS with "actual" as the root of the graph.
      InstructionHandle actual = (InstructionHandle) (iter.next());
      // Init colors
      for (int i = 0; i < all.length; i++) {
        colors.put(all[i], Color.white);
      }
      colors.put(actual, Color.gray);
      // Init Queue
      ArrayList<InstructionHandle> Q = new ArrayList<InstructionHandle>();
      Q.add(actual); // add(Obj) adds to the end, remove(0) removes from the start.

      /* BFS ALGORITHM MODIFICATION: Start out with multiple "root" nodes, as exception handlers are starting points of top-level code, too. [why top-level? TODO: Refer to the special JustIce notion of subroutines.]*/
      if (actual == all[0]) {
        for (int j = 0; j < handlers.length; j++) {
          colors.put(handlers[j].getHandlerPC(), Color.gray);
          Q.add(handlers[j].getHandlerPC());
        }
      }
      /* CONTINUE NORMAL BFS ALGORITHM */

      // Loop until Queue is empty
      while (Q.size() != 0) {
        InstructionHandle u = (InstructionHandle) Q.remove(0);
        InstructionHandle[] successors = getSuccessors(u);
        for (int i = 0; i < successors.length; i++) {
          if (((Color) colors.get(successors[i])) == Color.white) {
            colors.put(successors[i], Color.gray);
            Q.add(successors[i]);
          }
        }
        colors.put(u, Color.black);
      }
      // BFS ended above.
      for (int i = 0; i < all.length; i++) {
        if (colors.get(all[i]) == Color.black) {
          ((SubroutineImpl) (actual == all[0] ? getTopLevel() : getSubroutine(actual)))
              .addInstruction(all[i]);
          if (instructions_assigned.contains(all[i])) {
            throw new StructuralCodeConstraintException(
                "Instruction '"
                    + all[i]
                    + "' is part of more than one subroutine (or of the top level and a subroutine).");
          } else {
            instructions_assigned.add(all[i]);
          }
        }
      }
      if (actual != all[0]) { // If we don't deal with the top-level 'subroutine'
        ((SubroutineImpl) getSubroutine(actual)).setLeavingRET();
      }
    }

    // Now make sure no instruction of a Subroutine is protected by exception handling code
    // as is mandated by JustIces notion of subroutines.
    for (int i = 0; i < handlers.length; i++) {
      InstructionHandle _protected = handlers[i].getStartPC();
      while (_protected
          != handlers[i]
              .getEndPC()
              .getNext()) { // Note the inclusive/inclusive notation of "generic API" exception
        // handlers!
        Enumeration subs = subroutines.elements();
        while (subs.hasMoreElements()) {
          Subroutine sub = (Subroutine) subs.nextElement();
          if (sub
              != subroutines.get(all[0])) { // We don't want to forbid top-level exception handlers.
            if (sub.contains(_protected)) {
              throw new StructuralCodeConstraintException(
                  "Subroutine instruction '"
                      + _protected
                      + "' is protected by an exception handler, '"
                      + handlers[i]
                      + "'. This is forbidden by the JustIce verifier due to its clear definition of subroutines.");
            }
          }
        }
        _protected = _protected.getNext();
      }
    }

    // Now make sure no subroutine is calling a subroutine
    // that uses the same local variable for the RET as themselves
    // (recursively).
    // This includes that subroutines may not call themselves
    // recursively, even not through intermediate calls to other
    // subroutines.
    noRecursiveCalls(getTopLevel(), new HashSet<Integer>());
  }