@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));
      }
    }
  }
예제 #2
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;
    }
  }
예제 #3
0
파일: BCEL.java 프로젝트: tempbottle/ASM
 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();
 }
예제 #4
0
 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;
 }
예제 #5
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;
  }
예제 #6
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();
    }
  }
예제 #7
0
파일: BCEL.java 프로젝트: tempbottle/ASM
 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();
 }
예제 #8
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;
  }
예제 #9
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>());
  }
예제 #10
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;
  }