Example #1
0
  private boolean readClass(String clazz) throws IOException {
    ClassReader cr = new ClassReader(new FileInputStream(clazz));
    ClassNode ca =
        new ClassNode() {
          public void visitEnd() {
            // accept(cv);
          }
        };
    cr.accept(new CheckClassAdapter(ca), true);
    boolean failed = false;

    List methods = ca.methods;
    for (int i = 0; i < methods.size(); ++i) {
      MethodNode method = (MethodNode) methods.get(i);
      if (method.instructions.size() > 0) {
        Analyzer a = new Analyzer(new SimpleVerifier());
        try {
          a.analyze(ca.name, method);
          continue;
        } catch (Exception e) {
          e.printStackTrace();
        }
        final Frame[] frames = a.getFrames();

        if (!failed) {
          failed = true;
          log("verifying of class " + clazz + " failed");
        }
        if (verbose) log(method.name + method.desc);
        TraceMethodVisitor cv =
            new TraceMethodVisitor(null) {
              public void visitMaxs(int maxStack, int maxLocals) {
                StringBuffer buffer = new StringBuffer();
                for (int i = 0; i < text.size(); ++i) {
                  String s = frames[i] == null ? "null" : frames[i].toString();
                  while (s.length() < maxStack + maxLocals + 1) {
                    s += " ";
                  }
                  buffer.append(Integer.toString(i + 100000).substring(1));
                  buffer.append(" ");
                  buffer.append(s);
                  buffer.append(" : ");
                  buffer.append(text.get(i));
                }
                if (verbose) log(buffer.toString());
              }
            };
        for (int j = 0; j < method.instructions.size(); ++j) {
          Object insn = method.instructions.get(j);
          if (insn instanceof AbstractInsnNode) {
            ((AbstractInsnNode) insn).accept(cv);
          } else {
            cv.visitLabel((Label) insn);
          }
        }
        cv.visitMaxs(method.maxStack, method.maxLocals);
      }
    }
    return !failed;
  }
  @Override
  public void checkCall(
      @NonNull ClassContext context,
      @NonNull ClassNode classNode,
      @NonNull MethodNode method,
      @NonNull MethodInsnNode call) {
    String owner = call.owner;
    String desc = call.desc;
    if (owner.equals(OWNER_SECURE_RANDOM)) {
      if (desc.startsWith(LONG_ARG)) {
        checkValidSetSeed(context, call);
      } else if (desc.startsWith("([B)")) { // $NON-NLS-1$
        // setSeed(byte[]) ...
        // We could do some flow analysis here to see whether the byte array getting
        // passed in appears to be fixed.
        // However, people calling this constructor rather than the simpler one
        // with a fixed integer are probably less likely to make that mistake... right?
      }
    } else if (owner.equals(OWNER_RANDOM) && desc.startsWith(LONG_ARG)) {
      // Called setSeed(long) on an instanceof a Random object. Flag this if the instance
      // is likely a SecureRandom.

      // Track allocations such that we know whether the type of the call
      // is on a SecureRandom rather than a Random
      Analyzer analyzer =
          new Analyzer(
              new BasicInterpreter() {
                @Override
                public BasicValue newValue(Type type) {
                  if (type != null && type.getDescriptor().equals(VM_SECURE_RANDOM)) {
                    return new BasicValue(type);
                  }
                  return super.newValue(type);
                }
              });
      try {
        Frame[] frames = analyzer.analyze(classNode.name, method);
        InsnList instructions = method.instructions;
        Frame frame = frames[instructions.indexOf(call)];
        int stackSlot = frame.getStackSize();
        for (Type type : Type.getArgumentTypes(desc)) {
          stackSlot -= type.getSize();
        }
        BasicValue stackValue = (BasicValue) frame.getStack(stackSlot);
        Type type = stackValue.getType();
        if (type != null && type.getDescriptor().equals(VM_SECURE_RANDOM)) {
          checkValidSetSeed(context, call);
        }
      } catch (AnalyzerException e) {
        context.log(e, null);
      }
    } else if (owner.equals(OWNER_RANDOM) && desc.startsWith(LONG_ARG)) {
      // Called setSeed(long) on an instanceof a Random object. Flag this if the instance
      // is likely a SecureRandom.
      // TODO
    }
  }
Example #3
0
 public void visitEnd() {
   MethodNode mn = (MethodNode) mv;
   Analyzer<BasicValue> a = new Analyzer<BasicValue>(new BasicVerifier());
   try {
     a.analyze(owner, mn);
   } catch (AnalyzerException e) {
     throw new RuntimeException(e.getMessage());
   }
   mn.accept(next);
 }