Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
nimakarimipour committed Jul 19, 2024
1 parent 3f50938 commit e848053
Show file tree
Hide file tree
Showing 23 changed files with 27 additions and 2,065 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ publishing {
maven(MavenPublication) {
groupId = 'edu.ucr.cs.riple.taint'
artifactId = 'ucrtainting-checker'
version = '0.3-SNAPSHOT'
version = '0.3-ENHANCE-OFF-SNAPSHOT'

from components.java
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
import com.sun.source.tree.*;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import edu.ucr.cs.riple.taint.ucrtainting.handlers.CompositHandler;
import edu.ucr.cs.riple.taint.ucrtainting.handlers.Handler;
import edu.ucr.cs.riple.taint.ucrtainting.qual.RPolyTainted;
import edu.ucr.cs.riple.taint.ucrtainting.qual.RPossiblyValidated;
import edu.ucr.cs.riple.taint.ucrtainting.qual.RTainted;
Expand All @@ -43,20 +40,14 @@
import java.util.*;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.util.Elements;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.common.accumulation.AccumulationAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.framework.type.typeannotator.DefaultForTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.DefaultQualifierForUseTypeAnnotator;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.UserError;

public class UCRTaintingAnnotatedTypeFactory extends AccumulationAnnotatedTypeFactory {
Expand Down Expand Up @@ -90,8 +81,6 @@ public class UCRTaintingAnnotatedTypeFactory extends AccumulationAnnotatedTypeFa
public final AnnotationMirror rTainted;
/** AnnotationMirror for {@link RPolyTainted}. */
public final AnnotationMirror rPolyTainted;
/** The handler for the checker. Used to handle the custom logic of the checker. */
private final Handler handler;

public UCRTaintingAnnotatedTypeFactory(BaseTypeChecker checker) {
super(checker, RPossiblyValidated.class, RUntainted.class, null);
Expand Down Expand Up @@ -137,33 +126,9 @@ public UCRTaintingAnnotatedTypeFactory(BaseTypeChecker checker) {
this.rUntainted = AnnotationBuilder.fromClass(elements, RUntainted.class);
this.rTainted = AnnotationBuilder.fromClass(elements, RTainted.class);
this.rPolyTainted = AnnotationBuilder.fromClass(elements, RPolyTainted.class);
this.handler =
new CompositHandler(
this, ((JavacProcessingEnvironment) checker.getProcessingEnvironment()).getContext());
postInit();
}

@Override
protected TreeAnnotator createTreeAnnotator() {
return new ListTreeAnnotator(
super.createTreeAnnotator(), new UCRTaintingTreeAnnotator(this, handler));
}

@Override
protected void addAnnotationsFromDefaultForType(
@Nullable Element element, AnnotatedTypeMirror type) {
super.addAnnotationsFromDefaultForType(element, type);
// make reference type for var args untainted.
if (element instanceof Symbol.VarSymbol) {
if (((Symbol.VarSymbol) element).type instanceof Type.ArrayType) {
if (((Type.ArrayType) ((Symbol.VarSymbol) element).type).isVarargs()) {
makeUntainted(type);
}
}
}
handler.addAnnotationsFromDefaultForType(element, type);
}

@Override
protected DefaultQualifierForUseTypeAnnotator createDefaultForUseTypeAnnotator() {
return super.createDefaultForUseTypeAnnotator();
Expand All @@ -174,65 +139,17 @@ protected QualifierHierarchy createQualifierHierarchy() {
return new UCRTaintingQualifierHierarchy(this.getSupportedTypeQualifiers(), this.elements);
}

@Override
protected DefaultForTypeAnnotator createDefaultForTypeAnnotator() {
return new UCRTaintingTypeAnnotator(this);
}
// @Override
// protected DefaultForTypeAnnotator createDefaultForTypeAnnotator() {
// return new UCRTaintingTypeAnnotator(this);
// }

public AnnotationMirror rPossiblyValidatedAM(List<String> calledMethods) {
AnnotationBuilder builder = new AnnotationBuilder(processingEnv, RPossiblyValidated.class);
builder.setValue("value", calledMethods.toArray());
return builder.build();
}

/**
* Checks if any of the arguments of the node has been annotated with {@link RTainted}
*
* @param node to check for
* @return true if any argument is annotated with {@link RTainted}, false otherwise
*/
public boolean hasTaintedArgument(ExpressionTree node) {
List<? extends ExpressionTree> argumentsList = null;
if (node instanceof MethodInvocationTree) {
argumentsList = ((MethodInvocationTree) node).getArguments();
} else if (node instanceof NewClassTree) {
argumentsList = ((NewClassTree) node).getArguments();
}
if (node instanceof TypeCastTree) {
argumentsList = Collections.singletonList(((TypeCastTree) node).getExpression());
}
if (argumentsList != null) {
for (ExpressionTree eTree : argumentsList) {
if (mayBeTainted(getAnnotatedType(eTree))) {
return true;
}
}
}
return false;
}

/**
* Checks if the receiver tree has been annotated with {@link RTainted}
*
* @param node to check for
* @return true if annotated with {@link RTainted}, false otherwise
*/
public boolean hasTaintedReceiver(ExpressionTree node) {
if (node != null) {
ExpressionTree receiverTree = TreeUtils.getReceiverTree(node);
if (receiverTree != null) {
Element element = TreeUtils.elementFromTree(node);
if (element != null) {
Set<Modifier> modifiers = element.getModifiers();
return modifiers != null
&& !modifiers.contains(Modifier.STATIC)
&& getAnnotatedType(receiverTree).hasPrimaryAnnotation(rTainted);
}
}
}
return false;
}

/**
* Checks if the passed method is in unannotated code.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,13 @@

package edu.ucr.cs.riple.taint.ucrtainting;

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

import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import edu.ucr.cs.riple.taint.ucrtainting.handlers.UnannotatedCodeHandler;
import edu.ucr.cs.riple.taint.ucrtainting.serialization.SerializationService;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.common.accumulation.AccumulationChecker;
import org.checkerframework.framework.qual.StubFiles;
import org.checkerframework.framework.source.SupportedOptions;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.javacutil.TreeUtils;

/** This is the entry point for pluggable type-checking. */
@StubFiles({
Expand Down Expand Up @@ -93,21 +84,14 @@ public void initChecker() {
@Override
public void reportError(Object source, @CompilerMessageKey String messageKey, Object... args) {
pair = pair == null ? retrievePair(messageKey, args) : pair;
if (shouldBeSkipped(source, messageKey, pair, args)) {
return;
}
if (serialize) {
this.serializationService.serializeError(source, messageKey, pair);
}
args[args.length - 1] = args[args.length - 1].toString() + ", index: " + ++index;
super.reportError(source, messageKey, args);
}

public void detailedReportError(
Object source, @CompilerMessageKey String messageKey, FoundRequired pair, Object... args) {
if (shouldBeSkipped(source, messageKey, pair, args)) {
return;
}
this.serializationService.serializeError(source, messageKey, pair);
this.serialize = false;
this.pair = pair;
Expand Down Expand Up @@ -150,164 +134,4 @@ private FoundRequired retrievePair(String messageKey, Object... args) {
return null;
}
}

/**
* Determine if the error should be skipped.
*
* @param source The source of the error.
* @param messageKey The message key of the error.
* @param pair The pair of found and required annotated type mirrors.
* @param args Arguments passed to checker to create the error message
* @return True if the error should be skipped, false otherwise.
*/
private boolean shouldBeSkipped(
Object source, String messageKey, FoundRequired pair, Object[] args) {
Tree tree = (Tree) source;
if (source instanceof JCTree.JCTypeCast) {
ExpressionTree expression = ((JCTree.JCTypeCast) source).getExpression();
// check if expression is null literal
if (expression.getKind() == NULL_LITERAL) {
// skip errors where the cast is from null literal
return true;
}
}
// check if the expression is a member of annotation
if (shouldBeSkippedForAnnotationMemberSelection(source)) {
return true;
}

switch (messageKey) {
case "lambda.param":
case "enum.declaration":
return true;
// Skip errors that are caused by third-party code.
case "override.return":
{
Symbol.MethodSymbol overridingMethod =
(Symbol.MethodSymbol) TreeUtils.elementFromTree(visitor.getCurrentPath().getLeaf());
return overridingMethod == null || typeFactory.isUnannotatedMethod(overridingMethod);
}
// Skip errors that are caused by third-party code.
case "override.param":
{
if (!(args[6] instanceof AnnotatedTypeMirror.AnnotatedExecutableType)) {
return false;
}
AnnotatedTypeMirror.AnnotatedExecutableType overriddenType =
(AnnotatedTypeMirror.AnnotatedExecutableType) args[6];
Symbol.MethodSymbol overrideMethod = (Symbol.MethodSymbol) overriddenType.getElement();
return overrideMethod == null || typeFactory.isUnannotatedMethod(overrideMethod);
}
case "assignment":
case "return":
{
Tree errorTree = visitor.getCurrentPath().getLeaf();
ExpressionTree initializer = null;
if (errorTree instanceof JCTree.JCReturn) {
initializer = ((JCTree.JCReturn) errorTree).getExpression();
}
if (errorTree instanceof JCTree.JCVariableDecl) {
initializer = ((JCTree.JCVariableDecl) errorTree).getInitializer();
}
if (errorTree instanceof JCTree.JCAssign) {
initializer = ((JCTree.JCAssign) errorTree).getExpression();
}
if (!(initializer instanceof MethodInvocationTree)) {
return false;
}
boolean isApplicable =
UnannotatedCodeHandler.isSafeTransitionToUnAnnotatedCode(
(MethodInvocationTree) initializer, typeFactory);
if (!isApplicable) {
return false;
}
// check miss match is only try args which found is untainted, but required is tainted.
if (pair == null) {
return false;
}
if (!(pair.found instanceof AnnotatedTypeMirror.AnnotatedDeclaredType)
|| !(pair.required instanceof AnnotatedTypeMirror.AnnotatedDeclaredType)
|| !(pair.found.getUnderlyingType() instanceof Type.ClassType)
|| !(pair.required.getUnderlyingType() instanceof Type.ClassType)) {
return false;
}
AnnotatedTypeMirror.AnnotatedDeclaredType found =
(AnnotatedTypeMirror.AnnotatedDeclaredType) pair.found;
AnnotatedTypeMirror.AnnotatedDeclaredType required =
(AnnotatedTypeMirror.AnnotatedDeclaredType) pair.required;
Type.ClassType foundType = (Type.ClassType) found.getUnderlyingType();
Type.ClassType requiredType = (Type.ClassType) required.getUnderlyingType();
if (!foundType.tsym.equals(requiredType.tsym)) {
// We do not want to handle complex cases for now.
return false;
}
// all other mismatches should be ignored.
return !typeFactory.hasUntaintedAnnotation(required)
|| typeFactory.hasUntaintedAnnotation(found);
}
case "argument":
if (source instanceof ExpressionTree
&& TreeUtils.isExplicitThisDereference((ExpressionTree) source)) {
return true;
}
// Check if the tree is a argument of a method invocation which the invocation is a third
// party
if (visitor.getCurrentPath().getLeaf() instanceof JCTree.JCMethodInvocation) {
JCTree.JCMethodInvocation methodInvocation =
(JCTree.JCMethodInvocation) visitor.getCurrentPath().getLeaf();
Symbol.MethodSymbol methodSymbol =
(Symbol.MethodSymbol) TreeUtils.elementFromUse(methodInvocation);
if (methodSymbol != null && typeFactory.isUnannotatedMethod(methodSymbol)) {
// we want to silence errors where the mismatch is found: List<@RUntainted String> and
// required: List<@Tainted String>
if (pair != null) {
if (typeFactory.mayBeTainted(pair.found)
&& !typeFactory.mayBeTainted(pair.required)) {
return false;
}
if (pair.found instanceof AnnotatedTypeMirror.AnnotatedDeclaredType
&& pair.required instanceof AnnotatedTypeMirror.AnnotatedDeclaredType) {
AnnotatedTypeMirror.AnnotatedDeclaredType found =
(AnnotatedTypeMirror.AnnotatedDeclaredType) pair.found;
AnnotatedTypeMirror.AnnotatedDeclaredType required =
(AnnotatedTypeMirror.AnnotatedDeclaredType) pair.required;
boolean isSubtype = typeFactory.allTypeArgumentsAreSubType(found, required);
if (isSubtype) {
return true;
}
}
}
}
}
if (!(tree instanceof MethodInvocationTree)) {
return false;
}
return UnannotatedCodeHandler.isSafeTransitionToUnAnnotatedCode(
(MethodInvocationTree) tree, typeFactory);
default:
return false;
}
}

private boolean shouldBeSkippedForAnnotationMemberSelection(Object source) {
Tree exp = (Tree) source;
while (exp instanceof JCTree.JCTypeCast) {
exp = ((JCTree.JCTypeCast) exp).getExpression();
}
JCTree.JCFieldAccess fieldAccess = null;
if (exp instanceof JCTree.JCFieldAccess) {
fieldAccess = (JCTree.JCFieldAccess) exp;
}
if (exp instanceof JCTree.JCMethodInvocation) {
JCTree.JCMethodInvocation methodInvocation = (JCTree.JCMethodInvocation) exp;
if (methodInvocation.getMethodSelect() instanceof JCTree.JCFieldAccess) {
fieldAccess = (JCTree.JCFieldAccess) methodInvocation.getMethodSelect();
}
}
if (fieldAccess == null) {
return false;
}
Symbol.ClassSymbol owner = fieldAccess.sym.enclClass();
return owner != null && owner.isAnnotationType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,6 @@ public TransferResult<AccumulationValue, AccumulationStore> visitMethodInvocatio
// if the code is part of provided annotated packages or is present
// in the stub files, then we don't need any custom handling for it.
MethodInvocationTree tree = methodInvocationNode.getTree();
handleSideEffect(
tree,
result,
methodInvocationNode,
aTypeFactory.hasTaintedArgument(tree) && !aTypeFactory.hasTaintedReceiver(tree));
}
}

Expand All @@ -103,12 +98,6 @@ private void handleSideEffect(
Symbol.MethodSymbol symbol = (Symbol.MethodSymbol) TreeUtils.elementFromUse(tree);
if (aTypeFactory.isUnannotatedMethod(symbol) || rAnno.hasPrimaryAnnotation(RThis.class)) {
if (node.getTarget().getReceiver() instanceof MethodInvocationNode) {
handleSideEffect(
tree,
result,
(MethodInvocationNode) node.getTarget().getReceiver(),
(aTypeFactory.hasTaintedArgument(tree) && !aTypeFactory.hasTaintedReceiver(tree))
|| isTainted);
} else {
if (isTainted) {
makeStoresTainted(result, node.getTarget().getReceiver());
Expand Down
Loading

0 comments on commit e848053

Please sign in to comment.