Example usage for org.objectweb.asm.tree AbstractInsnNode getOpcode

List of usage examples for org.objectweb.asm.tree AbstractInsnNode getOpcode

Introduction

In this page you can find the example usage for org.objectweb.asm.tree AbstractInsnNode getOpcode.

Prototype

public int getOpcode() 

Source Link

Document

Returns the opcode of this instruction.

Usage

From source file:com.android.tools.lint.checks.FieldGetterDetector.java

License:Apache License

@Override
public void checkInstruction(@NonNull ClassContext context, @NonNull ClassNode classNode,
        @NonNull MethodNode method, @NonNull AbstractInsnNode instruction) {
    // As of Gingerbread/API 9, Dalvik performs this optimization automatically
    if (context.getProject().getMinSdk() >= 9) {
        return;/*from   ww  w. ja  v a2  s .c om*/
    }

    if ((method.access & Opcodes.ACC_STATIC) != 0) {
        // Not an instance method
        return;
    }

    if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) {
        return;
    }

    MethodInsnNode node = (MethodInsnNode) instruction;
    String name = node.name;
    String owner = node.owner;

    AbstractInsnNode prev = LintUtils.getPrevInstruction(instruction);
    if (prev == null || prev.getOpcode() != Opcodes.ALOAD) {
        return;
    }
    VarInsnNode prevVar = (VarInsnNode) prev;
    if (prevVar.var != 0) { // Not on "this", variable 0 in instance methods?
        return;
    }

    if (((name.startsWith("get") && name.length() > 3 //$NON-NLS-1$
            && Character.isUpperCase(name.charAt(3)))
            || (name.startsWith("is") && name.length() > 2 //$NON-NLS-1$
                    && Character.isUpperCase(name.charAt(2))))
            && owner.equals(classNode.name)) {
        // Calling a potential getter method on self. We now need to
        // investigate the method body of the getter call and make sure
        // it's really a plain getter, not just a method which happens
        // to have a method name like a getter, or a method which not
        // only returns a field but possibly computes it or performs
        // other initialization or side effects. This is done in a
        // second pass over the bytecode, initiated by the finish()
        // method.
        if (mPendingCalls == null) {
            mPendingCalls = new ArrayList<Entry>();
        }

        mPendingCalls.add(new Entry(name, node, method));
    }

    super.checkInstruction(context, classNode, method, instruction);
}

From source file:com.android.tools.lint.checks.JavaScriptInterfaceDetector.java

License:Apache License

@Nullable
private String findFirstArgType(ClassContext context, ClassNode classNode, MethodNode method,
        MethodInsnNode call) {//from  w w  w. jav  a2  s . c o m
    // Find object being passed in as the first argument
    Analyzer analyzer = new Analyzer(new SourceInterpreter() {
        @Override
        public SourceValue newOperation(AbstractInsnNode insn) {
            if (insn.getOpcode() == Opcodes.NEW) {
                String desc = ((TypeInsnNode) insn).desc;
                return new TypeValue(1, desc);
            }
            return super.newOperation(insn);
        }

        @Override
        public SourceValue newValue(Type type) {
            if (type != null && type.getSort() == Type.VOID) {
                return null;
            } else if (type != null) {
                return new TypeValue(1, type.getInternalName());
            }
            return super.newValue(type);
        }

        @Override
        public SourceValue copyOperation(AbstractInsnNode insn, SourceValue value) {
            return value;
        }
    });
    try {
        Frame[] frames = analyzer.analyze(classNode.name, method);
        InsnList instructions = method.instructions;
        Frame frame = frames[instructions.indexOf(call)];
        if (frame.getStackSize() <= 1) {
            return null;
        }
        SourceValue stackValue = (SourceValue) frame.getStack(1);
        if (stackValue instanceof TypeValue) {
            return ((TypeValue) stackValue).getFqcn();
        }
    } catch (AnalyzerException e) {
        context.log(e, null);
    }

    return null;
}

From source file:com.android.tools.lint.checks.LocaleDetector.java

License:Apache License

@Override
public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method,
        @NonNull MethodInsnNode call) {//from   w  w  w  .ja  v a2  s .com
    String owner = call.owner;
    String desc = call.desc;
    String name = call.name;
    if (owner.equals(DATE_FORMAT_OWNER)) {
        if (!name.equals(CONSTRUCTOR_NAME)) {
            return;
        }
        if (desc.equals("(Ljava/lang/String;Ljava/text/DateFormatSymbols;)V") //$NON-NLS-1$
                || desc.equals("()V") //$NON-NLS-1$
                || desc.equals("(Ljava/lang/String;)V")) { //$NON-NLS-1$
            Location location = context.getLocation(call);
            String message = "To get local formatting use getDateInstance(), getDateTimeInstance(), "
                    + "or getTimeInstance(), or use new SimpleDateFormat(String template, "
                    + "Locale locale) with for example Locale.US for ASCII dates.";
            context.report(DATE_FORMAT, method, call, location, message, null);
        }
        return;
    } else if (!owner.equals(STRING_OWNER)) {
        return;
    }

    if (name.equals(FORMAT_METHOD)) {
        // Only check the non-locale version of String.format
        if (!desc.equals("(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;")) { //$NON-NLS-1$
            return;
        }
        // Find the formatting string
        Analyzer analyzer = new Analyzer(new SourceInterpreter() {
            @Override
            public SourceValue newOperation(AbstractInsnNode insn) {
                if (insn.getOpcode() == Opcodes.LDC) {
                    Object cst = ((LdcInsnNode) insn).cst;
                    if (cst instanceof String) {
                        return new StringValue(1, (String) cst);
                    }
                }
                return super.newOperation(insn);
            }
        });
        try {
            Frame[] frames = analyzer.analyze(classNode.name, method);
            InsnList instructions = method.instructions;
            Frame frame = frames[instructions.indexOf(call)];
            if (frame.getStackSize() == 0) {
                return;
            }
            SourceValue stackValue = (SourceValue) frame.getStack(0);
            if (stackValue instanceof StringValue) {
                String format = ((StringValue) stackValue).getString();
                if (format != null && StringFormatDetector.isLocaleSpecific(format)) {
                    Location location = context.getLocation(call);
                    String message = "Implicitly using the default locale is a common source of bugs: "
                            + "Use String.format(Locale, ...) instead";
                    context.report(STRING_LOCALE, method, call, location, message, null);
                }
            }
        } catch (AnalyzerException e) {
            context.log(e, null);
        }
    } else {
        if (desc.equals("()Ljava/lang/String;")) { //$NON-NLS-1$
            Location location = context.getLocation(call);
            String message = String.format("Implicitly using the default locale is a common source of bugs: "
                    + "Use %1$s(Locale) instead", name);
            context.report(STRING_LOCALE, method, call, location, message, null);
        }
    }
}

From source file:com.android.tools.lint.checks.SecureRandomDetector.java

License:Apache License

private static void checkValidSetSeed(ClassContext context, MethodInsnNode call) {
    assert call.name.equals(SET_SEED);

    // Make sure the argument passed is not a literal
    AbstractInsnNode prev = LintUtils.getPrevInstruction(call);
    if (prev == null) {
        return;/* w  ww .  j a  v  a2 s .co  m*/
    }
    int opcode = prev.getOpcode();
    if (opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 || opcode == Opcodes.LDC) {
        context.report(ISSUE, context.getLocation(call),
                "Do not call setSeed() on a SecureRandom with a fixed seed: "
                        + "it is not secure. Use getSeed().",
                null);
    } else if (opcode == Opcodes.INVOKESTATIC) {
        String methodName = ((MethodInsnNode) prev).name;
        if (methodName.equals("currentTimeMillis") || methodName.equals("nanoTime")) {
            context.report(ISSUE, context.getLocation(call),
                    "It is dangerous to seed SecureRandom with the current time because "
                            + "that value is more predictable to an attacker than the default seed.",
                    null);
        }
    }
}

From source file:com.android.tools.lint.checks.SecureRandomGeneratorDetector.java

License:Apache License

@Override
public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method,
        @NonNull MethodInsnNode call) {/*from www  . jav  a 2 s  . c o  m*/
    if (mIgnore) {
        return;
    }

    String owner = call.owner;
    String name = call.name;

    // Look for the workaround code: if we see a Class.forName on the harmony NativeCrypto,
    // we'll consider that a sign.

    if (name.equals(FOR_NAME)) {
        if (call.getOpcode() != Opcodes.INVOKESTATIC || !owner.equals(JAVA_LANG_CLASS)) {
            return;
        }
        AbstractInsnNode prev = LintUtils.getPrevInstruction(call);
        if (prev instanceof LdcInsnNode) {
            Object cst = ((LdcInsnNode) prev).cst;
            //noinspection SpellCheckingInspection
            if (cst instanceof String && "org.apache.harmony.xnet.provider.jsse.NativeCrypto".equals(cst)) {
                mIgnore = true;
            }
        }
        return;
    }

    // Look for calls that probably require a properly initialized random number generator.
    assert owner.equals(JAVAX_CRYPTO_KEY_GENERATOR) || owner.equals(JAVA_SECURITY_KEY_PAIR_GENERATOR)
            || owner.equals(JAVAX_CRYPTO_KEY_AGREEMENT) || owner.equals(OWNER_SECURE_RANDOM)
            || owner.equals(JAVAX_CRYPTO_CIPHER) || owner.equals(JAVAX_CRYPTO_SIGNATURE)
            || owner.equals(JAVAX_NET_SSL_SSLENGINE) : owner;
    boolean warn = false;

    if (owner.equals(JAVAX_CRYPTO_SIGNATURE)) {
        warn = name.equals(INIT_SIGN);
    } else if (owner.equals(JAVAX_CRYPTO_CIPHER)) {
        if (name.equals(INIT)) {
            int arity = getDescArity(call.desc);
            AbstractInsnNode node = call;
            for (int i = 0; i < arity; i++) {
                node = LintUtils.getPrevInstruction(node);
                if (node == null) {
                    break;
                }
            }
            if (node != null) {
                int opcode = node.getOpcode();
                if (opcode == Opcodes.ICONST_3 || // Cipher.WRAP_MODE
                        opcode == Opcodes.ICONST_1) { // Cipher.ENCRYPT_MODE
                    warn = true;
                }
            }
        }
    } else if (name.equals(GET_INSTANCE) || name.equals(CONSTRUCTOR_NAME) || name.equals(WRAP)
            || name.equals(UNWRAP)) { // For SSLEngine
        warn = true;
    }

    if (warn) {
        if (mLocation != null) {
            return;
        }
        if (context.getMainProject().getMinSdk() > 18) {
            // Fix no longer needed
            mIgnore = true;
            return;
        }

        if (context.getDriver().isSuppressed(ISSUE, classNode, method, call)) {
            mIgnore = true;
        } else {
            mLocation = context.getLocation(call);
        }
    }
}

From source file:com.android.tools.lint.checks.TrustAllX509TrustManagerDetector.java

License:Apache License

@Override
@SuppressWarnings("rawtypes")
public void checkClass(@NonNull final ClassContext context, @NonNull ClassNode classNode) {
    if (!context.isFromClassLibrary()) {
        // Non-library code checked at the AST level
        return;/*from  w  ww .j a  va 2 s.  com*/
    }
    if (!classNode.interfaces.contains("javax/net/ssl/X509TrustManager")) {
        return;
    }
    List methodList = classNode.methods;
    for (Object m : methodList) {
        MethodNode method = (MethodNode) m;
        if ("checkServerTrusted".equals(method.name) || "checkClientTrusted".equals(method.name)) {
            InsnList nodes = method.instructions;
            boolean emptyMethod = true; // Stays true if method doesn't perform any "real"
                                        // operations
            for (int i = 0, n = nodes.size(); i < n; i++) {
                // Future work: Improve this check to be less sensitive to irrelevant
                // instructions/statements/invocations (e.g. System.out.println) by
                // looking for calls that could lead to a CertificateException being
                // thrown, e.g. throw statement within the method itself or invocation
                // of another method that may throw a CertificateException, and only
                // reporting an issue if none of these calls are found. ControlFlowGraph
                // may be useful here.
                AbstractInsnNode instruction = nodes.get(i);
                int type = instruction.getType();
                if (type != AbstractInsnNode.LABEL && type != AbstractInsnNode.LINE
                        && !(type == AbstractInsnNode.INSN && instruction.getOpcode() == Opcodes.RETURN)) {
                    emptyMethod = false;
                    break;
                }
            }
            if (emptyMethod) {
                Location location = context.getLocation(method, classNode);
                context.report(ISSUE, location, getErrorMessage(method.name));
            }
        }
    }
}

From source file:com.android.tools.lint.checks.WakelockDetector.java

License:Apache License

@Override
public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method,
        @NonNull MethodInsnNode call) {/*from ww  w .ja  v  a2  s .c  o  m*/
    if (!context.getProject().getReportIssues()) {
        // If this is a library project not being analyzed, ignore it
        return;
    }

    if (call.owner.equals(WAKELOCK_OWNER)) {
        String name = call.name;
        if (name.equals(ACQUIRE_METHOD)) {
            mHasAcquire = true;

            if (context.getDriver().getPhase() == 2) {
                assert !mHasRelease;
                context.report(ISSUE, method, call, context.getLocation(call),
                        "Found a wakelock acquire() but no release() calls anywhere", null);
            } else {
                assert context.getDriver().getPhase() == 1;
                // Perform flow analysis in this method to see if we're
                // performing an acquire/release block, where there are code paths
                // between the acquire and release which can result in the
                // release call not getting reached.
                checkFlow(context, classNode, method, call);
            }
        } else if (name.equals(RELEASE_METHOD)) {
            mHasRelease = true;

            // See if the release is happening in an onDestroy method, in an
            // activity.
            if ("onDestroy".equals(method.name) //$NON-NLS-1$
                    && context.getDriver().isSubclassOf(classNode, ANDROID_APP_ACTIVITY)) {
                context.report(ISSUE, method, call, context.getLocation(call),
                        "Wakelocks should be released in onPause, not onDestroy", null);
            }
        }
    } else if (call.owner.equals(POWER_MANAGER)) {
        if (call.name.equals(NEW_WAKE_LOCK_METHOD)) {
            AbstractInsnNode prev = LintUtils.getPrevInstruction(call);
            if (prev == null) {
                return;
            }
            prev = LintUtils.getPrevInstruction(prev);
            if (prev == null || prev.getOpcode() != Opcodes.LDC) {
                return;
            }
            LdcInsnNode ldc = (LdcInsnNode) prev;
            Object constant = ldc.cst;
            if (constant instanceof Integer) {
                int flag = ((Integer) constant).intValue();
                // Constant values are copied into the bytecode so we have to compare
                // values; however, that means the values are part of the API
                final int PARTIAL_WAKE_LOCK = 0x00000001;
                final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
                final int both = PARTIAL_WAKE_LOCK | ACQUIRE_CAUSES_WAKEUP;
                if ((flag & both) == both) {
                    context.report(ISSUE, method, call, context.getLocation(call),
                            "Should not set both PARTIAL_WAKE_LOCK and ACQUIRE_CAUSES_WAKEUP. "
                                    + "If you do not want the screen to turn on, get rid of "
                                    + "ACQUIRE_CAUSES_WAKEUP",
                            null);
                }
            }

        }
    }
}

From source file:com.android.tools.lint.checks.WakelockDetector.java

License:Apache License

/** Search from the given node towards the target; return false if we reach
 * an exit point such as a return or a call on the way there that is not within
 * a try/catch clause./*from  w ww .  j av a  2s .  c  om*/
 *
 * @param node the current node
 * @return true if the target was reached
 *    XXX RETURN VALUES ARE WRONG AS OF RIGHT NOW
 */
protected int dfs(ControlFlowGraph.Node node) {
    AbstractInsnNode instruction = node.instruction;
    if (instruction.getType() == AbstractInsnNode.JUMP_INSN) {
        int opcode = instruction.getOpcode();
        if (opcode == Opcodes.RETURN || opcode == Opcodes.ARETURN || opcode == Opcodes.LRETURN
                || opcode == Opcodes.IRETURN || opcode == Opcodes.DRETURN || opcode == Opcodes.FRETURN
                || opcode == Opcodes.ATHROW) {
            if (DEBUG) {
                System.out.println("Found exit via explicit return: " //$NON-NLS-1$
                        + node.toString(false));
            }
            return SEEN_RETURN;
        }
    }

    if (!DEBUG) {
        // There are no cycles, so no *NEED* for this, though it does avoid
        // researching shared labels. However, it makes debugging harder (no re-entry)
        // so this is only done when debugging is off
        if (node.visit != 0) {
            return 0;
        }
        node.visit = 1;
    }

    // Look for the target. This is any method call node which is a release on the
    // lock (later also check it's the same instance, though that's harder).
    // This is because finally blocks tend to be inlined so from a single try/catch/finally
    // with a release() in the finally, the bytecode can contain multiple repeated
    // (inlined) release() calls.
    if (instruction.getType() == AbstractInsnNode.METHOD_INSN) {
        MethodInsnNode method = (MethodInsnNode) instruction;
        if (method.name.equals(RELEASE_METHOD) && method.owner.equals(WAKELOCK_OWNER)) {
            return SEEN_TARGET;
        } else if (method.name.equals(ACQUIRE_METHOD) && method.owner.equals(WAKELOCK_OWNER)) {
            // OK
        } else if (method.name.equals(IS_HELD_METHOD) && method.owner.equals(WAKELOCK_OWNER)) {
            // OK
        } else {
            // Some non acquire/release method call: if this is not associated with a
            // try-catch block, it would mean the exception would exit the method,
            // which would be an error
            if (node.exceptions == null || node.exceptions.isEmpty()) {
                // Look up the corresponding frame, if any
                AbstractInsnNode curr = method.getPrevious();
                boolean foundFrame = false;
                while (curr != null) {
                    if (curr.getType() == AbstractInsnNode.FRAME) {
                        foundFrame = true;
                        break;
                    }
                    curr = curr.getPrevious();
                }

                if (!foundFrame) {
                    if (DEBUG) {
                        System.out.println("Found exit via unguarded method call: " //$NON-NLS-1$
                                + node.toString(false));
                    }
                    return SEEN_RETURN;
                }
            }
        }
    }

    // if (node.instruction is a call, and the call is not caught by
    // a try/catch block (provided the release is not inside the try/catch block)
    // then return false
    int status = 0;

    boolean implicitReturn = true;
    List<Node> successors = node.successors;
    List<Node> exceptions = node.exceptions;
    if (exceptions != null) {
        if (!exceptions.isEmpty()) {
            implicitReturn = false;
        }
        for (Node successor : exceptions) {
            status = dfs(successor) | status;
            if ((status & SEEN_RETURN) != 0) {
                if (DEBUG) {
                    System.out.println("Found exit via exception: " //$NON-NLS-1$
                            + node.toString(false));
                }
                return status;
            }
        }

        if (status != 0) {
            status |= SEEN_EXCEPTION;
        }
    }

    if (successors != null) {
        if (!successors.isEmpty()) {
            implicitReturn = false;
            if (successors.size() > 1) {
                status |= SEEN_BRANCH;
            }
        }
        for (Node successor : successors) {
            status = dfs(successor) | status;
            if ((status & SEEN_RETURN) != 0) {
                if (DEBUG) {
                    System.out.println("Found exit via branches: " //$NON-NLS-1$
                            + node.toString(false));
                }
                return status;
            }
        }
    }

    if (implicitReturn) {
        status |= SEEN_RETURN;
        if (DEBUG) {
            System.out.println("Found exit: via implicit return: " //$NON-NLS-1$
                    + node.toString(false));
        }
    }

    return status;
}

From source file:com.android.tools.lint.client.api.LintDriver.java

License:Apache License

@Nullable
private static MethodInsnNode findConstructorInvocation(@NonNull MethodNode method, @NonNull String className) {
    InsnList nodes = ((MethodNode) method).instructions;
    for (int i = 0, n = nodes.size(); i < n; i++) {
        AbstractInsnNode instruction = nodes.get(i);
        if (instruction.getOpcode() == Opcodes.INVOKESPECIAL) {
            MethodInsnNode call = (MethodInsnNode) instruction;
            if (className.equals(call.owner)) {
                return call;
            }/*w  w w . jav a 2  s .c o m*/
        }
    }

    return null;
}

From source file:com.builtbroken.mc.patch.ASMUtility.java

/**
 * Prints out all the info about a method
 *
 * @param methodNode - method/*from   ww w . j  a  va  2s  .co m*/
 */
public static void printMethod(MethodNode methodNode) {
    //TODO print rest of information
    ListIterator<AbstractInsnNode> it = methodNode.instructions.iterator();
    while (it.hasNext()) {
        AbstractInsnNode next = it.next();
        if (next instanceof MethodInsnNode) {
            System.out.println("MethodInsnNode( " + next.getOpcode() + ", " + ((MethodInsnNode) next).name
                    + ((MethodInsnNode) next).desc + " )");
        } else if (next instanceof VarInsnNode) {
            System.out.println("VarInsnNode( " + next.getOpcode() + ", " + ((VarInsnNode) next).var + " )");
        } else if (next instanceof LabelNode) {
            System.out.println("LabelNode( " + ((LabelNode) next).getLabel() + " )");
        } else if (next instanceof LineNumberNode) {
            System.out.println("LineNumberNode( " + ((LineNumberNode) next).line + " )");
        } else {
            System.out.println(next);
        }
    }
}