public TouchMethodVisitor(
      String owner,
      MethodNode methodNode,
      MethodVisitor methodVisitor,
      Set<Label> jumpLabels,
      Map<Label, Integer> lineLabels,
      Map<Label, SwitchHolder> switchLabels) {

    super(Opcodes.ASM5, methodVisitor);

    _owner = owner;
    _jumpLabels = jumpLabels;
    _lineLabels = lineLabels;
    _switchLabels = switchLabels;

    int variableCount = 0;

    if ((Opcodes.ACC_STATIC & methodNode.access) == 0) {
      variableCount++;
    }

    for (Type type : Type.getArgumentTypes(methodNode.desc)) {
      variableCount += type.getSize();
    }

    _variableCount = variableCount;
  }
  @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
    }
  }
Пример #3
0
 public void DUP(Type type) {
   switch (type.getSize()) {
     case 1:
       DUP();
       break;
     case 2:
       DUP2();
       break;
     default:
       throw new RuntimeException("Bad size");
   }
 }
Пример #4
0
  /**
   * Fetches return value or thrown exception. If return value is of basic type, it is automatically
   * boxed.
   *
   * @param mv output method visitor
   * @param type return data type
   * @return number of JVM stack slots emitted code consumes
   */
  public int emitFetchRetVal(SpyMethodVisitor mv, Type type) {

    if (Type.VOID == type.getSort()) {
      mv.visitInsn(ACONST_NULL);
      return 1;
    }

    mv.visitInsn(DUP);
    emitAutoboxing(mv, type);
    mv.visitVarInsn(ASTORE, mv.getRetValProbeSlot());

    return type.getSize();
  }
 private int remap(final int var, final Type type) {
   if (var + type.getSize() <= firstLocal) {
     return var;
   }
   int key = 2 * var + type.getSize() - 1;
   int size = mapping.length;
   if (key >= size) {
     int[] newMapping = new int[Math.max(2 * size, key + 1)];
     System.arraycopy(mapping, 0, newMapping, 0, size);
     mapping = newMapping;
   }
   int value = mapping[key];
   if (value == 0) {
     value = newLocalMapping(type);
     setLocalType(value, type);
     mapping[key] = value + 1;
   } else {
     value--;
   }
   if (value != var) {
     changed = true;
   }
   return value;
 }
 protected int newLocalMapping(final Type type) {
   int local = nextLocal;
   nextLocal += type.getSize();
   return local;
 }