Search in sources :

Example 1 with Unique

use of org.checkerframework.common.aliasing.qual.Unique in project checker-framework by typetools.

the class AliasingTransfer method visitAssignment.

/**
 * Case 1: For every assignment, the LHS is refined if the RHS has type {@literal @}Unique and is
 * a method invocation or a new class instance.
 */
@Override
public TransferResult<CFValue, CFStore> visitAssignment(AssignmentNode n, TransferInput<CFValue, CFStore> in) {
    Node rhs = n.getExpression();
    Tree treeRhs = rhs.getTree();
    AnnotatedTypeMirror rhsType = factory.getAnnotatedType(treeRhs);
    if (rhsType.hasAnnotation(Unique.class) && (rhs instanceof MethodInvocationNode || rhs instanceof ObjectCreationNode)) {
        // Do normal refinement.
        return super.visitAssignment(n, in);
    }
    // Widen the type of the rhs if the RHS's declared type wasn't @Unique.
    JavaExpression rhsExpr = JavaExpression.fromNode(rhs);
    in.getRegularStore().clearValue(rhsExpr);
    return new RegularTransferResult<>(null, in.getRegularStore());
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) Node(org.checkerframework.dataflow.cfg.node.Node) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) Tree(com.sun.source.tree.Tree) Unique(org.checkerframework.common.aliasing.qual.Unique) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) RegularTransferResult(org.checkerframework.dataflow.analysis.RegularTransferResult)

Example 2 with Unique

use of org.checkerframework.common.aliasing.qual.Unique in project checker-framework by typetools.

the class AliasingVisitor method canBeLeaked.

/**
 * Returns true if {@code exp} has type {@code @Unique} and is not a method invocation nor a new
 * class expression. It checks whether the tree expression is unique by either checking for an
 * explicit annotation or checking whether the class of the tree expression {@code exp} has type
 * {@code @Unique}
 *
 * @param exp the Tree to check
 * @return true if {@code exp} has type {@code @Unique} and is not a method invocation nor a new
 *     class expression
 */
private boolean canBeLeaked(Tree exp) {
    AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(exp);
    boolean isMethodInvocation = exp.getKind() == Tree.Kind.METHOD_INVOCATION;
    boolean isNewClass = exp.getKind() == Tree.Kind.NEW_CLASS;
    boolean isUniqueType = isUniqueClass(type) || type.hasExplicitAnnotation(Unique.class);
    return isUniqueType && !isMethodInvocation && !isNewClass;
}
Also used : Unique(org.checkerframework.common.aliasing.qual.Unique) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 3 with Unique

use of org.checkerframework.common.aliasing.qual.Unique in project checker-framework by typetools.

the class AliasingVisitor method visitVariable.

@Override
public Void visitVariable(VariableTree node, Void p) {
    // Component types are not allowed to have the @Unique annotation.
    AnnotatedTypeMirror varType = atypeFactory.getAnnotatedType(node);
    VariableElement elt = TreeUtils.elementFromDeclaration(node);
    if (elt.getKind().isField() && varType.hasExplicitAnnotation(Unique.class)) {
        checker.reportError(node, "unique.location.forbidden");
    } else if (node.getType().getKind() == Tree.Kind.ARRAY_TYPE) {
        AnnotatedArrayType arrayType = (AnnotatedArrayType) varType;
        if (arrayType.getComponentType().hasAnnotation(Unique.class)) {
            checker.reportError(node, "unique.location.forbidden");
        }
    } else if (node.getType().getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
        AnnotatedDeclaredType declaredType = (AnnotatedDeclaredType) varType;
        for (AnnotatedTypeMirror atm : declaredType.getTypeArguments()) {
            if (atm.hasAnnotation(Unique.class)) {
                checker.reportError(node, "unique.location.forbidden");
            }
        }
    }
    return super.visitVariable(node, p);
}
Also used : AnnotatedArrayType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) Unique(org.checkerframework.common.aliasing.qual.Unique) VariableElement(javax.lang.model.element.VariableElement) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 4 with Unique

use of org.checkerframework.common.aliasing.qual.Unique in project checker-framework by typetools.

the class AliasingVisitor method visitMethodInvocation.

/**
 * Checks that if a method call is being invoked inside a constructor with result type
 * {@literal @}Unique, it must not leak the "this" reference. There are 3 ways to make sure that
 * this is not happening:
 *
 * <ol>
 *   <li>{@code this} is not an argument of the method call.
 *   <li>{@code this} is an argument of the method call, but the respective parameter is annotated
 *       as {@literal @}NonLeaked.
 *   <li>{@code this} is an argument of the method call, but the respective parameter is annotated
 *       as {@literal @}LeakedToResult AND the result of the method call is not being stored (the
 *       method call is a statement).
 * </ol>
 *
 * The private method {@code isUniqueCheck} handles cases 2 and 3.
 */
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
    // @Unique. We also want to avoid visiting the <init> method.
    if (isInUniqueConstructor()) {
        if (TreeUtils.isSuperConstructorCall(node)) {
            // Check if a call to super() might create an alias: that
            // happens when the parent's respective constructor is not @Unique.
            AnnotatedTypeMirror superResult = atypeFactory.getAnnotatedType(node);
            if (!superResult.hasAnnotation(Unique.class)) {
                checker.reportError(node, "unique.leaked");
            }
        } else {
            // TODO: Currently the type of "this" doesn't always return the type of the constructor
            // result, therefore we need this "else" block. Once constructors are implemented correctly
            // we could remove that code below, since the type of "this" in a @Unique constructor will
            // be @Unique.
            Tree parent = getCurrentPath().getParentPath().getLeaf();
            boolean parentIsStatement = parent.getKind() == Tree.Kind.EXPRESSION_STATEMENT;
            ExecutableElement methodElement = TreeUtils.elementFromUse(node);
            List<? extends VariableElement> params = methodElement.getParameters();
            List<? extends ExpressionTree> args = node.getArguments();
            assert (args.size() == params.size()) : "Number of arguments in" + " the method call " + node + " is different from the " + "number of parameters for the method declaration: " + methodElement.getSimpleName();
            for (int i = 0; i < args.size(); i++) {
                // For every argument we check if it is a reference to "this".
                if (TreeUtils.isExplicitThisDereference(args.get(i))) {
                    // If it is a reference to "this", there is still hope that
                    // it is not being leaked (2. and 3. from the javadoc).
                    VariableElement param = params.get(i);
                    boolean hasNonLeaked = atypeFactory.getAnnotatedType(param).hasAnnotation(NonLeaked.class);
                    boolean hasLeakedToResult = atypeFactory.getAnnotatedType(param).hasAnnotation(LeakedToResult.class);
                    isUniqueCheck(node, parentIsStatement, hasNonLeaked, hasLeakedToResult);
                } else {
                // Not possible to leak reference here (case 1. from the javadoc).
                }
            }
            // Now, doing the same as above for the receiver parameter
            AnnotatedExecutableType annotatedType = atypeFactory.getAnnotatedType(methodElement);
            AnnotatedDeclaredType receiverType = annotatedType.getReceiverType();
            if (receiverType != null) {
                boolean hasNonLeaked = receiverType.hasAnnotation(NonLeaked.class);
                boolean hasLeakedToResult = receiverType.hasAnnotation(LeakedToResult.class);
                isUniqueCheck(node, parentIsStatement, hasNonLeaked, hasLeakedToResult);
            }
        }
    }
    return super.visitMethodInvocation(node, p);
}
Also used : AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) ExecutableElement(javax.lang.model.element.ExecutableElement) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) NewArrayTree(com.sun.source.tree.NewArrayTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ThrowTree(com.sun.source.tree.ThrowTree) Unique(org.checkerframework.common.aliasing.qual.Unique) VariableElement(javax.lang.model.element.VariableElement) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Aggregations

Unique (org.checkerframework.common.aliasing.qual.Unique)4 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)4 Tree (com.sun.source.tree.Tree)2 VariableElement (javax.lang.model.element.VariableElement)2 AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)2 ExpressionTree (com.sun.source.tree.ExpressionTree)1 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)1 MethodTree (com.sun.source.tree.MethodTree)1 NewArrayTree (com.sun.source.tree.NewArrayTree)1 ThrowTree (com.sun.source.tree.ThrowTree)1 VariableTree (com.sun.source.tree.VariableTree)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1 RegularTransferResult (org.checkerframework.dataflow.analysis.RegularTransferResult)1 AssignmentNode (org.checkerframework.dataflow.cfg.node.AssignmentNode)1 MethodInvocationNode (org.checkerframework.dataflow.cfg.node.MethodInvocationNode)1 Node (org.checkerframework.dataflow.cfg.node.Node)1 ObjectCreationNode (org.checkerframework.dataflow.cfg.node.ObjectCreationNode)1 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)1 AnnotatedArrayType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType)1 AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)1