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

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

Introduction

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

Prototype

int METHOD_INSN

To view the source code for org.objectweb.asm.tree AbstractInsnNode METHOD_INSN.

Click Source Link

Document

The type of MethodInsnNode instructions.

Usage

From source file:com.android.ide.eclipse.apt.internal.analysis.FloatAnalyzer.java

License:Apache License

@Override
protected Collection<Problem> analyzeMethod(final MethodNode methodNode) {
    final Collection<Problem> problems = new LinkedList<Problem>();
    final InsnList instructions = methodNode.instructions;
    for (int i = 0; i < instructions.size(); i++) {
        final AbstractInsnNode instruction = instructions.get(i);
        final int res = Arrays.binarySearch(FLOAT_OPERATIONS, instruction.getOpcode());
        boolean isProblem = res >= 0;
        if (!isProblem && instruction.getType() == AbstractInsnNode.METHOD_INSN) {
            final String owner = ((MethodInsnNode) instruction).owner;
            isProblem = FLOAT_CLASS.equals(owner);
        }// ww  w  .  j  av  a  2  s.c om
        if (isProblem) {
            final Problem problem = new Problem(instruction);
            if (!problems.contains(problem)) {
                problems.add(problem);
            }
        }
    }
    return problems;
}

From source file:com.android.ide.eclipse.apt.internal.analysis.InnerClassAnalyzer.java

License:Apache License

@Override
protected Collection<Problem> analyzeMethod(MethodNode methodNode) {
    final LinkedList<Problem> problems = new LinkedList<Problem>();
    final InsnList instructions = methodNode.instructions;
    for (int i = 0; i < instructions.size(); i++) {
        final AbstractInsnNode insnNode = instructions.get(i);
        if (insnNode.getOpcode() == Opcodes.INVOKESTATIC) {
            final MethodInsnNode method = (MethodInsnNode) insnNode;
            if (isStaticAccess(method)) {
                if (confirmParentClassAccess(methodNode, method)) {
                    final AbstractInsnNode inst = retrieveMethodOrField(method);
                    final int type = inst.getType();
                    if (type == AbstractInsnNode.FIELD_INSN || type == AbstractInsnNode.METHOD_INSN) {
                        final Problem problem = new Problem(inst);
                        problems.add(problem);
                    }// w  w w.  j a v a  2  s  . co m
                }
            }
        }
    }
    return problems;
}

From source file:com.android.tools.klint.checks.ControlFlowGraph.java

License:Apache License

/** Adds an exception try block node to this graph */
protected void exception(@NonNull AbstractInsnNode from, @NonNull TryCatchBlockNode tcb) {
    // Add tcb's to all instructions in the range
    LabelNode start = tcb.start;/*from  w  w  w  .  j a va 2s . c o m*/
    LabelNode end = tcb.end; // exclusive

    // Add exception edges for all method calls in the range
    AbstractInsnNode curr = start;
    Node handlerNode = getNode(tcb.handler);
    while (curr != end && curr != null) {
        if (curr.getType() == AbstractInsnNode.METHOD_INSN) {
            // Method call; add exception edge to handler
            if (tcb.type == null) {
                // finally block: not an exception path
                getNode(curr).addSuccessor(handlerNode);
            }
            getNode(curr).addExceptionPath(handlerNode);
        }
        curr = curr.getNext();
    }
}

From source file:com.android.tools.klint.client.api.AsmVisitor.java

License:Apache License

@SuppressWarnings("rawtypes") // ASM API uses raw types
void runClassDetectors(ClassContext context) {
    ClassNode classNode = context.getClassNode();

    for (Detector detector : mAllDetectors) {
        detector.beforeCheckFile(context);
    }//from  www  .j  a va  2 s  .  com

    for (Detector detector : mFullClassChecks) {
        Detector.ClassScanner scanner = (Detector.ClassScanner) detector;
        scanner.checkClass(context, classNode);
        detector.afterCheckFile(context);
    }

    if (!mMethodNameToChecks.isEmpty() || !mMethodOwnerToChecks.isEmpty()
            || mNodeTypeDetectors != null && mNodeTypeDetectors.length > 0) {
        List methodList = classNode.methods;
        for (Object m : methodList) {
            MethodNode method = (MethodNode) m;
            InsnList nodes = method.instructions;
            for (int i = 0, n = nodes.size(); i < n; i++) {
                AbstractInsnNode instruction = nodes.get(i);
                int type = instruction.getType();
                if (type == AbstractInsnNode.METHOD_INSN) {
                    MethodInsnNode call = (MethodInsnNode) instruction;

                    String owner = call.owner;
                    List<ClassScanner> scanners = mMethodOwnerToChecks.get(owner);
                    if (scanners != null) {
                        for (ClassScanner scanner : scanners) {
                            scanner.checkCall(context, classNode, method, call);
                        }
                    }

                    String name = call.name;
                    scanners = mMethodNameToChecks.get(name);
                    if (scanners != null) {
                        for (ClassScanner scanner : scanners) {
                            scanner.checkCall(context, classNode, method, call);
                        }
                    }
                }

                if (mNodeTypeDetectors != null && type < mNodeTypeDetectors.length) {
                    List<ClassScanner> scanners = mNodeTypeDetectors[type];
                    if (scanners != null) {
                        for (ClassScanner scanner : scanners) {
                            scanner.checkInstruction(context, classNode, method, instruction);
                        }
                    }
                }
            }
        }
    }

    for (Detector detector : mAllDetectors) {
        detector.afterCheckFile(context);
    }
}

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

License:Apache License

@SuppressWarnings("rawtypes") // ASM API
@Override// w  ww .j a  v  a 2  s  .  c om
public void checkClass(@NonNull final ClassContext context, @NonNull ClassNode classNode) {
    if (mApiDatabase == null) {
        return;
    }

    if (AOSP_BUILD && classNode.name.startsWith("android/support/")) { //$NON-NLS-1$
        return;
    }

    // Requires util package (add prebuilts/tools/common/asm-tools/asm-debug-all-4.0.jar)
    //classNode.accept(new TraceClassVisitor(new PrintWriter(System.out)));

    int classMinSdk = getClassMinSdk(context, classNode);
    if (classMinSdk == -1) {
        classMinSdk = getMinSdk(context);
    }

    List methodList = classNode.methods;
    if (methodList.isEmpty()) {
        return;
    }

    boolean checkCalls = context.isEnabled(UNSUPPORTED) || context.isEnabled(INLINED);
    boolean checkMethods = context.isEnabled(OVERRIDE) && context.getMainProject().getBuildSdk() >= 1;
    String frameworkParent = null;
    if (checkMethods) {
        LintDriver driver = context.getDriver();
        String owner = classNode.superName;
        while (owner != null) {
            // For virtual dispatch, walk up the inheritance chain checking
            // each inherited method
            if ((owner.startsWith("android/") //$NON-NLS-1$
                    && !owner.startsWith("android/support/")) //$NON-NLS-1$
                    || owner.startsWith("java/") //$NON-NLS-1$
                    || owner.startsWith("javax/")) { //$NON-NLS-1$
                frameworkParent = owner;
                break;
            }
            owner = driver.getSuperClass(owner);
        }
        if (frameworkParent == null) {
            checkMethods = false;
        }
    }

    if (checkCalls) { // Check implements/extends
        if (classNode.superName != null) {
            String signature = classNode.superName;
            checkExtendsClass(context, classNode, classMinSdk, signature);
        }
        if (classNode.interfaces != null) {
            @SuppressWarnings("unchecked") // ASM API
            List<String> interfaceList = classNode.interfaces;
            for (String signature : interfaceList) {
                checkExtendsClass(context, classNode, classMinSdk, signature);
            }
        }
    }

    for (Object m : methodList) {
        MethodNode method = (MethodNode) m;

        int minSdk = getLocalMinSdk(method.invisibleAnnotations);
        if (minSdk == -1) {
            minSdk = classMinSdk;
        }

        InsnList nodes = method.instructions;

        if (checkMethods && Character.isJavaIdentifierStart(method.name.charAt(0))) {
            int buildSdk = context.getMainProject().getBuildSdk();
            String name = method.name;
            assert frameworkParent != null;
            int api = mApiDatabase.getCallVersion(frameworkParent, name, method.desc);
            if (api > buildSdk && buildSdk != -1) {
                // TODO: Don't complain if it's annotated with @Override; that means
                // somehow the build target isn't correct.
                String fqcn;
                String owner = classNode.name;
                if (CONSTRUCTOR_NAME.equals(name)) {
                    fqcn = "new " + ClassContext.getFqcn(owner); //$NON-NLS-1$
                } else {
                    fqcn = ClassContext.getFqcn(owner) + '#' + name;
                }
                String message = String.format(
                        "This method is not overriding anything with the current build "
                                + "target, but will in API level %1$d (current target is %2$d): %3$s",
                        api, buildSdk, fqcn);

                Location location = context.getLocation(method, classNode);
                context.report(OVERRIDE, method, null, location, message, null);
            }
        }

        if (!checkCalls) {
            continue;
        }

        if (CHECK_DECLARATIONS) {
            // Check types in parameter list and types of local variables
            List localVariables = method.localVariables;
            if (localVariables != null) {
                for (Object v : localVariables) {
                    LocalVariableNode var = (LocalVariableNode) v;
                    String desc = var.desc;
                    if (desc.charAt(0) == 'L') {
                        // "Lpackage/Class;" => "package/Bar"
                        String className = desc.substring(1, desc.length() - 1);
                        int api = mApiDatabase.getClassVersion(className);
                        if (api > minSdk) {
                            String fqcn = ClassContext.getFqcn(className);
                            String message = String.format(
                                    "Class requires API level %1$d (current min is %2$d): %3$s", api, minSdk,
                                    fqcn);
                            report(context, message, var.start, method,
                                    className.substring(className.lastIndexOf('/') + 1), null,
                                    SearchHints.create(NEAREST).matchJavaSymbol());
                        }
                    }
                }
            }

            // Check return type
            // The parameter types are already handled as local variables so we can skip
            // right to the return type.
            // Check types in parameter list
            String signature = method.desc;
            if (signature != null) {
                int args = signature.indexOf(')');
                if (args != -1 && signature.charAt(args + 1) == 'L') {
                    String type = signature.substring(args + 2, signature.length() - 1);
                    int api = mApiDatabase.getClassVersion(type);
                    if (api > minSdk) {
                        String fqcn = ClassContext.getFqcn(type);
                        String message = String.format(
                                "Class requires API level %1$d (current min is %2$d): %3$s", api, minSdk, fqcn);
                        AbstractInsnNode first = nodes.size() > 0 ? nodes.get(0) : null;
                        report(context, message, first, method, method.name, null,
                                SearchHints.create(BACKWARD).matchJavaSymbol());
                    }
                }
            }
        }

        for (int i = 0, n = nodes.size(); i < n; i++) {
            AbstractInsnNode instruction = nodes.get(i);
            int type = instruction.getType();
            if (type == AbstractInsnNode.METHOD_INSN) {
                MethodInsnNode node = (MethodInsnNode) instruction;
                String name = node.name;
                String owner = node.owner;
                String desc = node.desc;

                // No need to check methods in this local class; we know they
                // won't be an API match
                if (node.getOpcode() == Opcodes.INVOKEVIRTUAL && owner.equals(classNode.name)) {
                    owner = classNode.superName;
                }

                boolean checkingSuperClass = false;
                while (owner != null) {
                    int api = mApiDatabase.getCallVersion(owner, name, desc);
                    if (api > minSdk) {
                        if (method.name.startsWith(SWITCH_TABLE_PREFIX)) {
                            // We're in a compiler-generated method to generate an
                            // array indexed by enum ordinal values to enum values. The enum
                            // itself must be requiring a higher API number than is
                            // currently used, but the call site for the switch statement
                            // will also be referencing it, so no need to report these
                            // calls.
                            break;
                        }

                        if (!checkingSuperClass && node.getOpcode() == Opcodes.INVOKEVIRTUAL
                                && methodDefinedLocally(classNode, name, desc)) {
                            break;
                        }

                        String fqcn;
                        if (CONSTRUCTOR_NAME.equals(name)) {
                            fqcn = "new " + ClassContext.getFqcn(owner); //$NON-NLS-1$
                        } else {
                            fqcn = ClassContext.getFqcn(owner) + '#' + name;
                        }
                        String message = String.format(
                                "Call requires API level %1$d (current min is %2$d): %3$s", api, minSdk, fqcn);

                        if (name.equals(ORDINAL_METHOD) && instruction.getNext() != null
                                && instruction.getNext().getNext() != null
                                && instruction.getNext().getOpcode() == Opcodes.IALOAD
                                && instruction.getNext().getNext().getOpcode() == Opcodes.TABLESWITCH) {
                            message = String.format(
                                    "Enum for switch requires API level %1$d " + "(current min is %2$d): %3$s",
                                    api, minSdk, ClassContext.getFqcn(owner));
                        }

                        report(context, message, node, method, name, null,
                                SearchHints.create(FORWARD).matchJavaSymbol());
                    }

                    // For virtual dispatch, walk up the inheritance chain checking
                    // each inherited method
                    if (owner.startsWith("android/") //$NON-NLS-1$
                            || owner.startsWith("javax/")) { //$NON-NLS-1$
                        // The API map has already inlined all inherited methods
                        // so no need to keep checking up the chain
                        // -- unless it's the support library which is also in
                        // the android/ namespace:
                        if (owner.startsWith("android/support/")) { //$NON-NLS-1$
                            owner = context.getDriver().getSuperClass(owner);
                        } else {
                            owner = null;
                        }
                    } else if (owner.startsWith("java/")) { //$NON-NLS-1$
                        if (owner.equals(LocaleDetector.DATE_FORMAT_OWNER)) {
                            checkSimpleDateFormat(context, method, node, minSdk);
                        }
                        // Already inlined; see comment above
                        owner = null;
                    } else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL) {
                        owner = context.getDriver().getSuperClass(owner);
                    } else if (node.getOpcode() == Opcodes.INVOKESTATIC && api == -1) {
                        // Inherit through static classes as well
                        owner = context.getDriver().getSuperClass(owner);
                    } else {
                        owner = null;
                    }

                    checkingSuperClass = true;
                }
            } else if (type == AbstractInsnNode.FIELD_INSN) {
                FieldInsnNode node = (FieldInsnNode) instruction;
                String name = node.name;
                String owner = node.owner;
                int api = mApiDatabase.getFieldVersion(owner, name);
                if (api > minSdk) {
                    if (method.name.startsWith(SWITCH_TABLE_PREFIX)) {
                        checkSwitchBlock(context, classNode, node, method, name, owner, api, minSdk);
                        continue;
                    }
                    String fqcn = ClassContext.getFqcn(owner) + '#' + name;
                    if (mPendingFields != null) {
                        mPendingFields.remove(fqcn);
                    }
                    String message = String.format("Field requires API level %1$d (current min is %2$d): %3$s",
                            api, minSdk, fqcn);
                    report(context, message, node, method, name, null,
                            SearchHints.create(FORWARD).matchJavaSymbol());
                }
            } else if (type == AbstractInsnNode.LDC_INSN) {
                LdcInsnNode node = (LdcInsnNode) instruction;
                if (node.cst instanceof Type) {
                    Type t = (Type) node.cst;
                    String className = t.getInternalName();

                    int api = mApiDatabase.getClassVersion(className);
                    if (api > minSdk) {
                        String fqcn = ClassContext.getFqcn(className);
                        String message = String.format(
                                "Class requires API level %1$d (current min is %2$d): %3$s", api, minSdk, fqcn);
                        report(context, message, node, method,
                                className.substring(className.lastIndexOf('/') + 1), null,
                                SearchHints.create(FORWARD).matchJavaSymbol());
                    }
                }
            }
        }
    }
}

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

License:Apache License

@SuppressWarnings("unchecked") // ASM API
public static void scanForAndCheckSetOnTouchListenerCalls(ClassContext context, ClassNode classNode) {
    List<MethodNode> methods = classNode.methods;
    for (MethodNode methodNode : methods) {
        ListIterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
        while (iterator.hasNext()) {
            AbstractInsnNode abstractInsnNode = iterator.next();
            if (abstractInsnNode.getType() == AbstractInsnNode.METHOD_INSN) {
                MethodInsnNode methodInsnNode = (MethodInsnNode) abstractInsnNode;
                if (methodInsnNode.name.equals(SET_ON_TOUCH_LISTENER)
                        && methodInsnNode.desc.equals(SET_ON_TOUCH_LISTENER_SIG)) {
                    checkSetOnTouchListenerCall(context, methodNode, methodInsnNode);
                }//from   w ww.  j a v a2  s  .c om
            }
        }
    }
}

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

License:Apache License

@SuppressWarnings("unchecked") // ASM API
@Nullable/*ww w  . j  a v a  2 s.co  m*/
private static AbstractInsnNode findMethodCallInstruction(@NonNull InsnList instructions, @NonNull String owner,
        @NonNull String name, @NonNull String desc) {
    ListIterator<AbstractInsnNode> iterator = instructions.iterator();

    while (iterator.hasNext()) {
        AbstractInsnNode insnNode = iterator.next();
        if (insnNode.getType() == AbstractInsnNode.METHOD_INSN) {
            MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
            if ((methodInsnNode.owner.equals(owner)) && (methodInsnNode.name.equals(name))
                    && (methodInsnNode.desc.equals(desc))) {
                return methodInsnNode;
            }
        }
    }

    return null;
}

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

License:Apache License

@Override
public int[] getApplicableAsmNodeTypes() {
    return new int[] { AbstractInsnNode.METHOD_INSN };
}

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

License:Apache License

@SuppressWarnings("rawtypes") // ASM API
@Override/*w w  w  .  j  a  v a  2s . co  m*/
public void checkClass(@NonNull final ClassContext context, @NonNull ClassNode classNode) {
    if (!context.isFromClassLibrary() || shouldSkip(context.file)) {
        return;
    }

    if (mApiDatabase == null) {
        return;
    }

    if (classNode.name.startsWith(JAVAX_PKG_PREFIX)) {
        mJavaxLibraryClasses.add(classNode.name);
    }

    List methodList = classNode.methods;
    for (Object m : methodList) {
        MethodNode method = (MethodNode) m;

        InsnList nodes = method.instructions;

        // Check return type
        // The parameter types are already handled as local variables so we can skip
        // right to the return type.
        // Check types in parameter list
        String signature = method.desc;
        if (signature != null) {
            int args = signature.indexOf(')');
            if (args != -1 && signature.charAt(args + 1) == 'L') {
                String type = signature.substring(args + 2, signature.length() - 1);
                if (isInvalidPackage(type)) {
                    AbstractInsnNode first = nodes.size() > 0 ? nodes.get(0) : null;
                    record(context, method, first, type);
                }
            }
        }

        for (int i = 0, n = nodes.size(); i < n; i++) {
            AbstractInsnNode instruction = nodes.get(i);
            int type = instruction.getType();
            if (type == AbstractInsnNode.METHOD_INSN) {
                MethodInsnNode node = (MethodInsnNode) instruction;
                String owner = node.owner;

                // No need to check methods in this local class; we know they
                // won't be an API match
                if (node.getOpcode() == Opcodes.INVOKEVIRTUAL && owner.equals(classNode.name)) {
                    owner = classNode.superName;
                }

                while (owner != null) {
                    if (isInvalidPackage(owner)) {
                        record(context, method, instruction, owner);
                    }

                    // For virtual dispatch, walk up the inheritance chain checking
                    // each inherited method
                    if (owner.startsWith("android/") //$NON-NLS-1$
                            || owner.startsWith(JAVA_PKG_PREFIX) || owner.startsWith(JAVAX_PKG_PREFIX)) {
                        owner = null;
                    } else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL) {
                        owner = context.getDriver().getSuperClass(owner);
                    } else if (node.getOpcode() == Opcodes.INVOKESTATIC) {
                        // Inherit through static classes as well
                        owner = context.getDriver().getSuperClass(owner);
                    } else {
                        owner = null;
                    }
                }
            } else if (type == AbstractInsnNode.FIELD_INSN) {
                FieldInsnNode node = (FieldInsnNode) instruction;
                String owner = node.owner;
                if (isInvalidPackage(owner)) {
                    record(context, method, instruction, owner);
                }
            } else if (type == AbstractInsnNode.LDC_INSN) {
                LdcInsnNode node = (LdcInsnNode) instruction;
                if (node.cst instanceof Type) {
                    Type t = (Type) node.cst;
                    String className = t.getInternalName();
                    if (isInvalidPackage(className)) {
                        record(context, method, instruction, className);
                    }
                }
            }
        }
    }
}

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

License:Apache License

@SuppressWarnings("rawtypes")
public void checkClass(@NonNull final ClassContext context, @NonNull ClassNode classNode) {
    // If class isn't in mReceiversWithIntentFilter (set below by
    // XmlScanner), skip it.
    if (!mReceiversWithProtectedBroadcastIntentFilter.contains(classNode.name)) {
        return;/*from w  w w .  ja  va 2  s. co  m*/
    }

    // Search for "void onReceive(android.content.Context, android.content.Intent)" method
    List methodList = classNode.methods;

    for (Object m : methodList) {
        MethodNode method = (MethodNode) m;
        if (!"onReceive".equals(method.name)
                || !"(Landroid/content/Context;Landroid/content/Intent;)V".equals(method.desc)) {
            continue;
        }
        // Search for call to getAction but also search for references to aload_2,
        // which indicates that the method is making use of the received intent in
        // some way.
        //
        // If the onReceive method doesn't call getAction but does make use of
        // the received intent, it is possible that it is passing it to another
        // method that might be performing the getAction check, so we warn that the
        // finding may be a false positive. (An alternative option would be to not
        // report a finding at all in this case.)
        boolean getActionEncountered = false;
        boolean intentParameterEncountered = false;
        InsnList nodes = method.instructions;
        for (int i = 0, n = nodes.size(); i < n; i++) {
            AbstractInsnNode instruction = nodes.get(i);
            int type = instruction.getType();
            if (type == AbstractInsnNode.VAR_INSN) {
                VarInsnNode node = (VarInsnNode) instruction;
                if (node.getOpcode() == Opcodes.ALOAD) {
                    if (node.var == 2) {
                        intentParameterEncountered = true;
                    }
                }
            } else if (type == AbstractInsnNode.METHOD_INSN) {
                MethodInsnNode node = (MethodInsnNode) instruction;
                if ("android/content/Intent".equals(node.owner) && "getAction".equals(node.name)) {
                    getActionEncountered = true;
                    break;
                }
            }
        }
        if (!getActionEncountered) {
            Location location = context.getLocation(method, classNode);
            String report;
            if (!intentParameterEncountered) {
                report = "This broadcast receiver declares an intent-filter for a protected "
                        + "broadcast action string, which can only be sent by the system, "
                        + "not third-party applications. However, the receiver's onReceive "
                        + "method does not appear to call getAction to ensure that the "
                        + "received Intent's action string matches the expected value, "
                        + "potentially making it possible for another actor to send a "
                        + "spoofed intent with no action string or a different action "
                        + "string and cause undesired behavior.";
            } else {
                // An alternative implementation option is to not report a finding at all in
                // this case, if we are worried about false positives causing confusion or
                // resulting in developers ignoring other lint warnings.
                report = "This broadcast receiver declares an intent-filter for a protected "
                        + "broadcast action string, which can only be sent by the system, "
                        + "not third-party applications. However, the receiver's onReceive "
                        + "method does not appear to call getAction to ensure that the "
                        + "received Intent's action string matches the expected value, "
                        + "potentially making it possible for another actor to send a "
                        + "spoofed intent with no action string or a different action "
                        + "string and cause undesired behavior. In this case, it is "
                        + "possible that the onReceive method passed the received Intent "
                        + "to another method that checked the action string. If so, this "
                        + "finding can safely be ignored.";
            }
            context.report(ACTION_STRING, method, null, location, report);
        }
    }
}