package checkers.tainting;
import com.sun.source.tree.*;
import checkers.basetype.BaseTypeChecker;
import checkers.tainting.quals.Untainted;
import checkers.types.AnnotatedTypeMirror;
import checkers.types.BasicAnnotatedTypeFactory;
import checkers.types.TreeAnnotator;
import checkers.util.TreeUtils;
/**
* Adds implicit and default {@code Untainted} annotation, only if the user
* does not explicitly insert them.
* <p/>
*
* This factory will add the {@link Untainted} annotation to a type if the
* input is
*
* <ol>
* <li value="1">a string literal (Note: Handled by Unqualified meta-annotation)
* <li value="2">a string concatenation where both operands are untainted
* </ol>
*
*/
public class TaintingAnnotatedTypeFactory
extends BasicAnnotatedTypeFactory<TaintingChecker> {
public TaintingAnnotatedTypeFactory(TaintingChecker checker,
CompilationUnitTree root) {
super(checker, root);
}
/*
* Override createTreeAnnotator to customize type based on tree kind
* and content.
*/
protected TreeAnnotator createTreeAnnotator(TaintingChecker checker) {
return new TaintingTreeAnnotator(checker);
}
/*
* To insert an annotation for a kind of a tree, FOO, override
* the appropriate visitFOO method and modify the passed
* AnnotationTypeMirror
*/
private class TaintingTreeAnnotator extends TreeAnnotator {
public TaintingTreeAnnotator(BaseTypeChecker checker) {
super(checker, TaintingAnnotatedTypeFactory.this);
}
/**
* Handles String concatenation. The result of concatenating
* untainted strings is also untainted String.
*
* Note: Flow infers the rule for '+=' from here
*/
@Override
public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) {
if (TreeUtils.isStringConcatenation(tree)) {
AnnotatedTypeMirror lExpr = getAnnotatedType(tree.getLeftOperand());
AnnotatedTypeMirror rExpr = getAnnotatedType(tree.getRightOperand());
if (lExpr.hasAnnotation(Untainted.class) && rExpr.hasAnnotation(Untainted.class))
type.addAnnotation(Untainted.class);
}
return super.visitBinary(tree, type);
}
// For now, assume all string literals are untainted
// /**
// * Performs extra checks for string literal to determine its taintness
// */
// @Override
// public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) {
// if (tree.getKind() == Tree.Kind.STRING_LITERAL) {
// LiteralTree sl = (LiteralTree)tree;
// String str = (String)sl.getValue();
//
// if (isUntaintedValue(str)) {
// type.addAnnotation(Untainted.class);
// }
// }
// return super.visitLiteral(tree, type);
// }
//
// private boolean isUntaintedValue(String s) {
// throw new RuntimeException("Not implemented yet");
// }
}
}