All Downloads are FREE. Search and download functionalities are using the official Maven repository.

framework.src.org.checkerframework.common.aliasing.AliasingTransfer Maven / Gradle / Ivy

Go to download

Checker Qual is the set of annotations (qualifiers) and supporting classes used by the Checker Framework to type check Java source code. Please see artifact: org.checkerframework:checker

There is a newer version: 3.45.0
Show newest version
package org.checkerframework.common.aliasing;

import java.util.List;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;

import org.checkerframework.common.aliasing.qual.LeakedToResult;
import org.checkerframework.common.aliasing.qual.NonLeaked;
import org.checkerframework.common.aliasing.qual.Unique;
import org.checkerframework.dataflow.analysis.FlowExpressions;
import org.checkerframework.dataflow.analysis.FlowExpressions.Receiver;
import org.checkerframework.dataflow.analysis.RegularTransferResult;
import org.checkerframework.dataflow.analysis.TransferInput;
import org.checkerframework.dataflow.analysis.TransferResult;
import org.checkerframework.dataflow.cfg.node.AssignmentNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.ObjectCreationNode;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFStore;
import org.checkerframework.framework.flow.CFTransfer;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.javacutil.TreeUtils;

import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;

/**
 * Type refinement is treated in the usual way, except that at
 * (pseudo-)assignments the RHS may lose its type refinement, before the LHS is
 * type-refined.
 *
 * The RHS always loses its type refinement (it is widened to
 * {@literal @}MaybeAliased, and its declared type must have been
 * {@literal @}MaybeAliased) except in the following cases:
 * 

* 1.The RHS is a fresh expression. *

* 2.The LHS is a {@literal @}NonLeaked formal parameter and the RHS is an * argument in a method call or constructor invocation. *

* 3.The LHS is a {@literal @}LeakedToResult formal parameter, the RHS is an * argument in a method call or constructor invocation, and the method's return * value is discarded. */ public class AliasingTransfer extends CFTransfer { private AnnotatedTypeFactory factory; public AliasingTransfer( CFAbstractAnalysis analysis) { super(analysis); factory = analysis.getTypeFactory(); } /** * 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 visitAssignment(AssignmentNode n, TransferInput 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)) { return super.visitAssignment(n, in); // Do normal refinement. } // Widen the type of the rhs if the RHS's declared type wasn't @Unique. Receiver r = FlowExpressions.internalReprOf(factory, rhs); in.getRegularStore().clearValue(r); return new RegularTransferResult<>(null, in.getRegularStore()); } /** * Handling pseudo-assignments. Called by * CFAbstractTransfer.visitMethodInvocation(). *

* Case 2: Given a method call, traverses all formal parameters of the * method declaration, and if it doesn't have the {@literal @}NonLeaked or * {@literal @}LeakedToResult annotations, we remove the node of the * respective argument in the method call from the store. If parameter has * {@literal @}LeakedToResult, visitMethodInvocation() handles it. */ @Override protected void processPostconditions(MethodInvocationNode n, CFStore store, ExecutableElement methodElement, Tree tree) { super.processPostconditions(n, store, methodElement, tree); if (TreeUtils.isEnumSuper(n.getTree())) { // Skipping the init() method for enums. return; } List args = n.getArguments(); List params = methodElement.getParameters(); assert (args.size() == params.size()) : "Number of arguments in " + "the method call " + n.toString() + " is different from the" + " number of parameters for the method declaration: " + methodElement.getSimpleName().toString(); AnnotatedExecutableType annotatedType = factory.getAnnotatedType(methodElement); List paramTypes = annotatedType.getParameterTypes(); for (int i = 0; i < args.size(); i++) { Node arg = args.get(i); AnnotatedTypeMirror paramType = paramTypes.get(i); if (!paramType.hasAnnotation(NonLeaked.class) && !paramType.hasAnnotation(LeakedToResult.class)) { store.clearValue(FlowExpressions.internalReprOf(factory, arg)); } } // Now, doing the same as above for the receiver parameter Node receiver = n.getTarget().getReceiver(); AnnotatedDeclaredType receiverType = annotatedType.getReceiverType(); if (receiverType != null && !receiverType.hasAnnotation(LeakedToResult.class) && !receiverType.hasAnnotation(NonLeaked.class)) { store.clearValue(FlowExpressions.internalReprOf(factory, receiver)); } } /** * Case 3: Given a method invocation expression, if the parent of the * expression is not a statement, check if there are any arguments of the * method call annotated as {@literal @}LeakedToResult and remove it from the * store, since it might be leaked. */ @Override public TransferResult visitMethodInvocation( MethodInvocationNode n, TransferInput in) { Tree parent = n.getTreePath().getParentPath().getLeaf(); boolean parentIsStatement = parent.getKind() == Kind.EXPRESSION_STATEMENT; if (!parentIsStatement) { ExecutableElement methodElement = TreeUtils.elementFromUse(n.getTree()); List args = n.getArguments(); List params = methodElement .getParameters(); assert (args.size() == params.size()) : "Number of arguments in " + "the method call " + n.toString() + " is different from the" + " number of parameters for the method declaration: " + methodElement.getSimpleName().toString(); CFStore store = in.getRegularStore(); for (int i = 0; i < args.size(); i++) { Node arg = args.get(i); VariableElement param = params.get(i); if (factory.getAnnotatedType(param).hasAnnotation(LeakedToResult.class)) { // If argument can leak to result, and parent is not a // single statement, remove that node from store. store.clearValue(FlowExpressions.internalReprOf(factory, arg)); } } // Now, doing the same as above for the receiver parameter Node receiver = n.getTarget().getReceiver(); AnnotatedExecutableType annotatedType = factory.getAnnotatedType(methodElement); AnnotatedDeclaredType receiverType = annotatedType.getReceiverType(); if (receiverType != null && receiverType.hasAnnotation(LeakedToResult.class)) { store.clearValue(FlowExpressions.internalReprOf(factory, receiver)); } } // If parent is a statement, processPostconditions will handle the // pseudo-assignments. return super.visitMethodInvocation(n, in); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy