com.h3xstream.findsecbugs.injection.AbstractTaintDetector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of findsecbugs-plugin Show documentation
Show all versions of findsecbugs-plugin Show documentation
Core module of the project. It include all the SpotBugs detectors.
The resulting jar is the published plugin.
The newest version!
/**
* Find Security Bugs
* Copyright (c) Philippe Arteau, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.h3xstream.findsecbugs.injection;
import com.h3xstream.findsecbugs.taintanalysis.TaintDataflow;
import com.h3xstream.findsecbugs.taintanalysis.TaintFrame;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.Detector;
import edu.umd.cs.findbugs.ba.CFGBuilderException;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
import edu.umd.cs.findbugs.ba.Location;
import edu.umd.cs.findbugs.bcel.BCELUtil;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
import java.util.Iterator;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.MethodGen;
/**
* Detector designed for extension to allow usage of taint analysis
*
* @author David Formanek (Y Soft Corporation, a.s.)
*/
public abstract class AbstractTaintDetector implements Detector {
protected final BugReporter bugReporter;
protected AbstractTaintDetector(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
/**
* Allow any concrete implementation of taint detector to skip the analysis of certain files.
* The purpose can be for optimisation or to trigger bug in specific context.
*
* The default implementation returns true to all classes visited.
*
* @param classContext Information about the class that is about to be analyzed
* @return If the given class should be analyze.
*/
public boolean shouldAnalyzeClass(ClassContext classContext) {
return true;
}
@Override
public void visitClassContext(ClassContext classContext) {
if(!shouldAnalyzeClass(classContext)) {
return;
}
for (Method method : classContext.getMethodsInCallOrder()) {
if (classContext.getMethodGen(method) == null) {
continue;
}
if (!method.isStatic()) {
continue;
}
try {
analyzeMethod(classContext, method);
} catch (CheckedAnalysisException e) {
logException(classContext, method, e);
} catch (RuntimeException e) {
logException(classContext, method, e);
}
}
for (Method method : classContext.getMethodsInCallOrder()) {
if (classContext.getMethodGen(method) == null) {
continue;
}
if (method.isStatic()) {
continue;
}
try {
analyzeMethod(classContext, method);
} catch (CheckedAnalysisException e) {
logException(classContext, method, e);
} catch (RuntimeException e) {
logException(classContext, method, e);
}
}
}
@Override
public void report() {
}
protected void analyzeMethod(ClassContext classContext, Method method)
throws CheckedAnalysisException {
TaintDataflow dataflow = getTaintDataFlow(classContext, method);
ConstantPoolGen cpg = classContext.getConstantPoolGen();
ClassMethodSignature classMethodSignature = new ClassMethodSignature(
com.h3xstream.findsecbugs.BCELUtil.getSlashedClassName(classContext.getJavaClass()), method.getName(), method.getSignature());
for (Iterator i = getLocationIterator(classContext, method); i.hasNext();) {
Location location = i.next();
InstructionHandle handle = location.getHandle();
Instruction instruction = handle.getInstruction();
if (!(instruction instanceof InvokeInstruction)) {
continue;
}
InvokeInstruction invoke = (InvokeInstruction) instruction;
TaintFrame fact = dataflow.getFactAtLocation(location);
assert fact != null;
if (!fact.isValid()) {
continue;
}
analyzeLocation(classContext, method, handle, cpg, invoke, fact, classMethodSignature);
}
}
private static Iterator getLocationIterator(ClassContext classContext, Method method)
throws CheckedAnalysisException {
try {
return classContext.getCFG(method).locationIterator();
} catch (CFGBuilderException ex) {
throw new CheckedAnalysisException("cannot get control flow graph", ex);
}
}
private static TaintDataflow getTaintDataFlow(ClassContext classContext, Method method)
throws CheckedAnalysisException {
MethodDescriptor descriptor = BCELUtil.getMethodDescriptor(classContext.getJavaClass(), method);
return Global.getAnalysisCache().getMethodAnalysis(TaintDataflow.class, descriptor);
}
private void logException(ClassContext classContext, Method method, Exception ex) {
bugReporter.logError("Exception while analyzing "
+ classContext.getFullyQualifiedMethodName(method), ex);
}
abstract protected void analyzeLocation(ClassContext classContext, Method method, InstructionHandle handle,
ConstantPoolGen cpg, InvokeInstruction invoke, TaintFrame fact, ClassMethodSignature classMethodSignature)
throws DataflowAnalysisException;
}