Skip to content

Commit

Permalink
Merge pull request #107 from formanek/master
Browse files Browse the repository at this point in the history
Inheritance aware taint analysis, extended collections support
  • Loading branch information
h3xstream committed Oct 9, 2015
2 parents e46f1ca + b368ec4 commit c2d4141
Show file tree
Hide file tree
Showing 12 changed files with 775 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import edu.umd.cs.findbugs.Detector;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.CFGBuilderException;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
Expand All @@ -46,6 +47,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
Expand Down Expand Up @@ -114,7 +117,7 @@ private void analyzeMethod(ClassContext classContext, Method method, Collection<
}
SourceLineAnnotation sourceLine = SourceLineAnnotation
.fromVisitedInstruction(classContext, method, handle);
checkTaintSink(getFullMethodName(cpg, invoke), fact, sourceLine, currentMethod);
checkTaintSink(cpg, invoke, fact, sourceLine, currentMethod);
InjectionPoint injectionPoint = getInjectionPoint(invoke, cpg, handle, selectedSources);
for (int offset : injectionPoint.getInjectableArguments()) {
Taint parameterTaint = fact.getStackValue(offset);
Expand All @@ -123,7 +126,6 @@ private void analyzeMethod(ClassContext classContext, Method method, Collection<
continue;
}
BugInstance bugInstance = new BugInstance(this, injectionPoint.getBugType(), priority);

bugInstance.addClassAndMethod(classContext.getJavaClass(), method);
bugInstance.addSourceLine(sourceLine);
if (injectionPoint.getInjectableMethod() != null) {
Expand All @@ -143,35 +145,86 @@ private static Iterator<Location> getLocationIterator(ClassContext classContext,
}
}

private void checkTaintSink(String calledMethod, TaintFrame fact,
private void checkTaintSink(ConstantPoolGen cpg, InvokeInstruction invoke, TaintFrame fact,
SourceLineAnnotation sourceLine, String currentMethod) throws DataflowAnalysisException {
if (methodsWithSinks.containsKey(calledMethod)) {
Set<TaintSink> sinks = methodsWithSinks.get(calledMethod);
for (TaintSink sink : sinks) {
Taint sinkTaint = sink.getTaint();
Set<Integer> taintParameters = sinkTaint.getParameters();
Taint finalTaint = Taint.valueOf(sinkTaint.getNonParametricState());
for (Integer offset : taintParameters) {
Taint parameterTaint = fact.getStackValue(offset);
finalTaint = Taint.merge(finalTaint, parameterTaint);
}
if (finalTaint == null) {
continue;
}
for (TaintSink sink : getSinks(cpg, invoke, fact)) {
Taint sinkTaint = sink.getTaint();
Set<Integer> taintParameters = sinkTaint.getParameters();
Taint finalTaint = Taint.valueOf(sinkTaint.getNonParametricState());
for (Integer offset : taintParameters) {
Taint parameterTaint = fact.getStackValue(offset);
finalTaint = Taint.merge(finalTaint, parameterTaint);
}
if (finalTaint == null) {
continue;
}
if (finalTaint.isTainted() || finalTaint.hasParameters()) {
BugInstance bugInstance = sink.getBugInstance();
bugInstance.addSourceLine(sourceLine);
addSourceLines(finalTaint.getLocations(), bugInstance);
if (finalTaint.isTainted()) {
BugInstance bugInstance = sink.getBugInstance();
bugInstance.setPriority(Priorities.HIGH_PRIORITY);
bugInstance.addSourceLine(sourceLine);
} else if (finalTaint.hasParameters()) {
} else {
assert finalTaint.isUnknown();
BugInstance bugInstance = sink.getBugInstance();
bugInstance.addSourceLine(sourceLine);
delayBugToReport(currentMethod, finalTaint, bugInstance);
}
}
}
}

private Set<TaintSink> getSinks(ConstantPoolGen cpg, InvokeInstruction invoke, TaintFrame frame) {
String className = getInstanceClassName(cpg, invoke, frame);
String methodName = "." + invoke.getMethodName(cpg) + invoke.getSignature(cpg);
Set<TaintSink> sinks = methodsWithSinks.get(className.concat(methodName));
if (sinks != null) {
return sinks;
}
try {
JavaClass javaClass = Repository.lookupClass(className);
assert javaClass != null;
return getSuperSinks(javaClass, methodName);
} catch (ClassNotFoundException ex) {
AnalysisContext.reportMissingClass(ex);
}
return Collections.emptySet();
}

private Set<TaintSink> getSuperSinks(JavaClass javaClass, String method) throws ClassNotFoundException {
for (JavaClass superClass : javaClass.getSuperClasses()) {
String fullMethodName = superClass.getClassName().replace('.', '/').concat(method);
Set<TaintSink> sinks = methodsWithSinks.get(fullMethodName);
if (sinks != null) {
return sinks;
}
}
for (JavaClass interfaceClass : javaClass.getAllInterfaces()) {
String fullMethodName = interfaceClass.getClassName().replace('.', '/').concat(method);
Set<TaintSink> sinks = methodsWithSinks.get(fullMethodName);
if (sinks != null) {
return sinks;
}
}
return Collections.emptySet();
}

private static String getInstanceClassName(ConstantPoolGen cpg, InvokeInstruction invoke, TaintFrame frame) {
try {
int instanceIndex = frame.getNumArgumentsIncludingObjectInstance(invoke, cpg) - 1;
if (instanceIndex != -1) {
assert instanceIndex < frame.getStackDepth();
Taint instanceTaint = frame.getStackValue(instanceIndex);
String className = instanceTaint.getRealInstanceClassName();
if (className != null) {
return className;
}
}
} catch (DataflowAnalysisException ex) {
assert false : ex.getMessage();
}
String dottedClassName = invoke.getReferenceType(cpg).toString();
return ClassName.toSlashedClassName(dottedClassName);
}

private static InjectionPoint getInjectionPoint(InvokeInstruction invoke, ConstantPoolGen cpg,
InstructionHandle handle, Collection<InjectionSource> sources) {
InjectionPoint injectionPoint = null;
Expand Down Expand Up @@ -199,7 +252,9 @@ private void reportBug(BugInstance bugInstance, Taint taint, String currentMetho
private void delayBugToReport(String method, Taint taint, BugInstance bug) {
TaintSink taintSink = new TaintSink(taint, bug);
Set<TaintSink> sinkSet = methodsWithSinks.get(method);
if(sinkSet == null) sinkSet = new HashSet<TaintSink>();
if (sinkSet == null) {
sinkSet = new HashSet<TaintSink>();
}
sinkSet.add(taintSink);
methodsWithSinks.put(method, sinkSet);
}
Expand Down Expand Up @@ -248,13 +303,6 @@ private void logException(ClassContext classContext, Method method, Exception ex
+ classContext.getFullyQualifiedMethodName(method), ex);
}

private static String getFullMethodName(ConstantPoolGen cpg, InvokeInstruction invoke) {
String dottedClassName = invoke.getReferenceType(cpg).toString();
StringBuilder builder = new StringBuilder(ClassName.toSlashedClassName(dottedClassName));
builder.append(".").append(invoke.getMethodName(cpg)).append(invoke.getSignature(cpg));
return builder.toString();
}

private static String getFullMethodName(MethodGen methodGen) {
String methodNameWithSignature = methodGen.getName() + methodGen.getSignature();
String slashedClassName = methodGen.getClassName().replace('.', '/');
Expand Down

0 comments on commit c2d4141

Please sign in to comment.