609 lines
21 KiB
Java
609 lines
21 KiB
Java
/*
|
|
* This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html.
|
|
*
|
|
* This file is a derivative of code released under the terms listed below.
|
|
*
|
|
*/
|
|
/*
|
|
*
|
|
* Copyright (c) 2009-2012,
|
|
*
|
|
* Adam Fuchs <afuchs@cs.umd.edu>
|
|
* Avik Chaudhuri <avik@cs.umd.edu>
|
|
* Steve Suh <suhsteve@gmail.com>
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3. The names of the contributors may not be used to endorse or promote
|
|
* products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*
|
|
*/
|
|
|
|
package org.scandroid.flow.functions;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.scandroid.domain.CodeElement;
|
|
import org.scandroid.domain.DomainElement;
|
|
import org.scandroid.domain.FieldElement;
|
|
import org.scandroid.domain.IFDSTaintDomain;
|
|
import org.scandroid.domain.InstanceKeyElement;
|
|
import org.scandroid.domain.LocalElement;
|
|
import org.scandroid.domain.ReturnElement;
|
|
import org.scandroid.flow.types.FlowType;
|
|
|
|
import com.ibm.wala.classLoader.IClass;
|
|
import com.ibm.wala.classLoader.IField;
|
|
import com.ibm.wala.classLoader.IMethod;
|
|
import com.ibm.wala.dataflow.IFDS.IFlowFunction;
|
|
import com.ibm.wala.dataflow.IFDS.IFlowFunctionMap;
|
|
import com.ibm.wala.dataflow.IFDS.ISupergraph;
|
|
import com.ibm.wala.dataflow.IFDS.IUnaryFlowFunction;
|
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey;
|
|
import com.ibm.wala.ipa.cfg.BasicBlockInContext;
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|
import com.ibm.wala.ssa.ISSABasicBlock;
|
|
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
|
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
|
|
import com.ibm.wala.ssa.SSAGetInstruction;
|
|
import com.ibm.wala.ssa.SSAInstruction;
|
|
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
|
import com.ibm.wala.ssa.SSAPutInstruction;
|
|
import com.ibm.wala.ssa.SSAReturnInstruction;
|
|
import com.ibm.wala.types.FieldReference;
|
|
import com.ibm.wala.types.MethodReference;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.util.collections.HashMapFactory;
|
|
import com.ibm.wala.util.collections.HashSetFactory;
|
|
import com.ibm.wala.util.intset.BitVectorIntSet;
|
|
import com.ibm.wala.util.intset.IntSet;
|
|
import com.ibm.wala.util.intset.MutableIntSet;
|
|
import com.ibm.wala.util.intset.MutableSparseIntSet;
|
|
import com.ibm.wala.util.intset.OrdinalSet;
|
|
|
|
|
|
/**
|
|
* @deprecated Replaced by TaintTransferFunctions.
|
|
*/
|
|
@Deprecated
|
|
public class IFDSTaintFlowFunctionProvider<E extends ISSABasicBlock>
|
|
implements IFlowFunctionMap<BasicBlockInContext<E>> {
|
|
|
|
private final IFDSTaintDomain<E> domain;
|
|
private final ISupergraph<BasicBlockInContext<E>,CGNode> graph;
|
|
private final PointerAnalysis<InstanceKey> pa;
|
|
|
|
public IFDSTaintFlowFunctionProvider(IFDSTaintDomain<E> domain,
|
|
ISupergraph<BasicBlockInContext<E>, CGNode> graph,
|
|
PointerAnalysis<InstanceKey> pa)
|
|
{
|
|
this.domain = domain;
|
|
this.graph = graph;
|
|
this.pa = pa;
|
|
}
|
|
|
|
// instruction has a valid def set
|
|
private static boolean inFlow(SSAInstruction instruction) {
|
|
return (instruction instanceof SSAArrayLoadInstruction) ||
|
|
(instruction instanceof SSAGetInstruction);
|
|
}
|
|
|
|
// instruction's def is getUse(0)
|
|
private static boolean outFlow(SSAInstruction instruction) {
|
|
return (instruction instanceof SSAArrayStoreInstruction) ||
|
|
(instruction instanceof SSAPutInstruction) ||
|
|
(instruction instanceof SSAInvokeInstruction);
|
|
}
|
|
|
|
// instruction is a return instruction
|
|
private static boolean returnFlow(SSAInstruction instruction) {
|
|
return (instruction instanceof SSAReturnInstruction);
|
|
}
|
|
|
|
private static class UseDefSetPair
|
|
{
|
|
public Set<CodeElement> uses = HashSetFactory.make();
|
|
public Set<CodeElement> defs = HashSetFactory.make();
|
|
}
|
|
|
|
private class DefUse implements IUnaryFlowFunction {
|
|
|
|
private final List<UseDefSetPair> useToDefList = new ArrayList<>();
|
|
|
|
private final BasicBlockInContext<E> bb;
|
|
|
|
public DefUse(final BasicBlockInContext<E> inBlock) {
|
|
|
|
this.bb = inBlock;
|
|
|
|
for (SSAInstruction instruction : bb) {
|
|
handleInstruction(instruction);
|
|
}
|
|
}
|
|
|
|
private void handleInstruction(SSAInstruction instruction) {
|
|
// System.out.println("handle instruction: "+instruction);
|
|
|
|
UseDefSetPair p = new UseDefSetPair();
|
|
boolean thisToResult = false;
|
|
if(instruction instanceof SSAInvokeInstruction)
|
|
{
|
|
thisToResult = handleInvokeInstruction(instruction, p);
|
|
}
|
|
if (thisToResult) {
|
|
useToDefList.add(p);
|
|
p = new UseDefSetPair();
|
|
}
|
|
|
|
IClassHierarchy ch = bb.getNode().getClassHierarchy();
|
|
|
|
if (inFlow(instruction)) {
|
|
handleInflowInstruction(instruction, p, ch);
|
|
}
|
|
else if (outFlow(instruction)) {
|
|
handleOutflowInstruction(instruction, p, ch);
|
|
}
|
|
else if(returnFlow(instruction))
|
|
{
|
|
handleReturnFlowInstruction(instruction, p);
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < instruction.getNumberOfUses(); i++) {
|
|
p.uses.addAll(CodeElement.valueElements(instruction.getUse(i)));
|
|
}
|
|
for (int j = 0; j < instruction.getNumberOfDefs(); j++) {
|
|
p.defs.addAll(CodeElement.valueElements(instruction.getDef(j)));
|
|
}
|
|
}
|
|
|
|
useToDefList.add(p);
|
|
}
|
|
|
|
private void handleReturnFlowInstruction(SSAInstruction instruction,
|
|
UseDefSetPair p) {
|
|
SSAReturnInstruction retInst = (SSAReturnInstruction)instruction;
|
|
if(retInst.getNumberOfUses() > 0)
|
|
{
|
|
/* TODO: why not add instance keys, too? */
|
|
for(int i = 0; i < instruction.getNumberOfUses(); i++)
|
|
{
|
|
//p.uses.add(new LocalElement(instruction.getUse(i)));
|
|
p.uses.addAll(
|
|
CodeElement.valueElements(instruction.getUse(i)));
|
|
|
|
}
|
|
p.defs.add(new ReturnElement());
|
|
}
|
|
}
|
|
|
|
private boolean handleInvokeInstruction(SSAInstruction instruction,
|
|
UseDefSetPair p) {
|
|
boolean thisToResult;
|
|
SSAInvokeInstruction invInst = (SSAInvokeInstruction)instruction;
|
|
if(!invInst.isSpecial() && !invInst.isStatic() && instruction.getNumberOfDefs() > 0)
|
|
{
|
|
//System.out.println("adding receiver flow in "+this+" for "+invInst);
|
|
//System.out.println("\tadding local element "+invInst.getReceiver());
|
|
//getReceiver() == getUse(0) == param[0] == this
|
|
p.uses.addAll(CodeElement.valueElements(invInst.getReceiver()));
|
|
for(int i = 0; i < invInst.getNumberOfDefs(); i++)
|
|
{
|
|
//System.out.println("\tadding def local element "+invInst.getDef(i));
|
|
//return valuenumber of invoke instruction
|
|
p.defs.addAll(CodeElement.valueElements(invInst.getDef(i)));
|
|
}
|
|
}
|
|
thisToResult = true;
|
|
return thisToResult;
|
|
}
|
|
|
|
private void handleInflowInstruction(SSAInstruction instruction,
|
|
UseDefSetPair p, IClassHierarchy ch) {
|
|
if (instruction instanceof SSAGetInstruction) {
|
|
handleInflowGetInstruction(instruction, p, ch);
|
|
}
|
|
else if (instruction instanceof SSAArrayLoadInstruction){
|
|
handleInflowArrayLoadInstruction(instruction, p);
|
|
}
|
|
}
|
|
|
|
private void handleOutflowInstruction(SSAInstruction instruction,
|
|
UseDefSetPair p, IClassHierarchy ch) {
|
|
if (instruction instanceof SSAPutInstruction) {
|
|
handleOutflowPutInstruction(instruction, p, ch);
|
|
}
|
|
else if (instruction instanceof SSAArrayStoreInstruction){
|
|
handleOutflowArrayStoreInstruction(instruction, p);
|
|
}
|
|
else if (instruction instanceof SSAInvokeInstruction){
|
|
|
|
handleOutflowInvokeInstruction(instruction, p);
|
|
}
|
|
}
|
|
|
|
private void handleOutflowInvokeInstruction(SSAInstruction instruction,
|
|
UseDefSetPair p) {
|
|
MethodReference targetMethod = ((SSAInvokeInstruction) instruction).getCallSite().getDeclaredTarget();
|
|
if (methodExcluded(targetMethod)) {
|
|
// TODO make all parameters flow into all other
|
|
// parameters, which could happen in the static case as well.
|
|
if (!((SSAInvokeInstruction) instruction).isStatic()) {
|
|
// These loops cause all parameters flow into the
|
|
// 'this' param (due to instruction.getUse(0))
|
|
for (int i = 1; i < instruction.getNumberOfUses(); i++) {
|
|
p.uses.addAll(CodeElement.valueElements(instruction.getUse(i)));
|
|
}
|
|
|
|
|
|
if (instruction.getNumberOfUses() > 0) {
|
|
p.defs.addAll(CodeElement.valueElements(instruction.getUse(0)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void handleOutflowArrayStoreInstruction(
|
|
SSAInstruction instruction, UseDefSetPair p) {
|
|
p.uses.addAll(CodeElement.valueElements(instruction.getUse(2)));
|
|
p.defs.addAll(CodeElement.valueElements(instruction.getUse(0)));
|
|
}
|
|
|
|
private void handleOutflowPutInstruction(SSAInstruction instruction,
|
|
UseDefSetPair p, IClassHierarchy ch) {
|
|
SSAPutInstruction pi = (SSAPutInstruction)instruction;
|
|
PointerKey pk;
|
|
Set<CodeElement> elements = HashSetFactory.make();
|
|
if (pi.isStatic()) {
|
|
p.uses.addAll(CodeElement.valueElements(instruction.getUse(0)));
|
|
FieldReference declaredField = pi.getDeclaredField();
|
|
IField staticField = getStaticIField(ch, declaredField);
|
|
if (staticField == null) {
|
|
pk = null;
|
|
} else {
|
|
pk = new StaticFieldKey(staticField);
|
|
}
|
|
} else {
|
|
p.uses.addAll(
|
|
CodeElement.valueElements(instruction.getUse(1)));
|
|
|
|
// this value number seems to be the object referenced in this instruction (?)
|
|
int valueNumber = instruction.getUse(0);
|
|
pk = new LocalPointerKey(bb.getNode(), valueNumber);
|
|
|
|
//MyLogger.log(LogLevel.DEBUG, " instruction: "+instruction);
|
|
|
|
// add the object that holds the field that was modified
|
|
// to the list of things tainted by this flow:
|
|
p.defs.addAll(CodeElement.valueElements(valueNumber));
|
|
}
|
|
// now add the field keys to the defs list so that they
|
|
// are also tainted:
|
|
if (pk!=null) {
|
|
OrdinalSet<InstanceKey> m = pa.getPointsToSet(pk);
|
|
if (m != null) {
|
|
for (InstanceKey instanceKey : m) {
|
|
elements.add(new FieldElement(instanceKey, pi.getDeclaredField()));
|
|
elements.add(new InstanceKeyElement(instanceKey));
|
|
}
|
|
}
|
|
p.defs.addAll(elements);
|
|
}
|
|
}
|
|
|
|
private void handleInflowArrayLoadInstruction(
|
|
SSAInstruction instruction, UseDefSetPair p) {
|
|
p.uses.addAll(CodeElement.valueElements(instruction.getUse(0)));
|
|
p.defs.addAll(CodeElement.valueElements(instruction.getDef()));
|
|
}
|
|
|
|
private void handleInflowGetInstruction(SSAInstruction instruction,
|
|
UseDefSetPair p, IClassHierarchy ch) {
|
|
SSAGetInstruction gi = (SSAGetInstruction)instruction;
|
|
|
|
PointerKey pk;
|
|
FieldReference declaredField = gi.getDeclaredField();
|
|
if ( gi.isStatic()) {
|
|
IField staticField =
|
|
getStaticIField(ch, declaredField);
|
|
|
|
if (staticField == null) {
|
|
pk = null;
|
|
} else {
|
|
pk = new StaticFieldKey(staticField);
|
|
}
|
|
} else {
|
|
int valueNumber = instruction.getUse(0);
|
|
pk = new LocalPointerKey(bb.getNode(), valueNumber);
|
|
}
|
|
|
|
if (pk!=null) {
|
|
Set<CodeElement> elements = HashSetFactory.make();
|
|
OrdinalSet<InstanceKey> m = pa.getPointsToSet(pk);
|
|
if(m != null) {
|
|
for (InstanceKey instanceKey : m) {
|
|
elements.add(new FieldElement(instanceKey, declaredField));
|
|
elements.add(new InstanceKeyElement(instanceKey));
|
|
}
|
|
}
|
|
p.uses.addAll(elements);
|
|
//getinstruction only has 1 def
|
|
p.defs.add(new LocalElement(instruction.getDef(0)));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determines if the provide method is in the exclusions by checking the supergraph.
|
|
* @param method
|
|
* @return True if the method can not be found in the supergraph.
|
|
*/
|
|
private boolean methodExcluded(MethodReference method) {
|
|
Collection<IMethod> iMethods = pa.getClassHierarchy().getPossibleTargets(method);
|
|
return 0 == iMethods.size();
|
|
}
|
|
|
|
private IField getStaticIField(IClassHierarchy ch,
|
|
FieldReference declaredField) {
|
|
TypeReference staticTypeRef = declaredField.getDeclaringClass();
|
|
|
|
IClass staticClass = ch.lookupClass(staticTypeRef);
|
|
|
|
//referring to a static field which we don't have loaded in the class hierarchy
|
|
//possibly ignored in the exclusions file or just not included in the scope
|
|
if (staticClass == null)
|
|
return null;
|
|
|
|
IField staticField =
|
|
staticClass.getField(declaredField.getName());
|
|
return staticField;
|
|
}
|
|
|
|
private void addTargets(CodeElement d1, MutableIntSet set, FlowType<E> taintType)
|
|
{
|
|
//System.out.println(this.toString()+".addTargets("+d1+"...)");
|
|
for(UseDefSetPair p: useToDefList)
|
|
{
|
|
if(p.uses.contains(d1))
|
|
{
|
|
//System.out.println("\t\tfound pair that uses "+d1);
|
|
for(CodeElement i:p.defs)
|
|
{
|
|
//System.out.println("\t\tadding outflow "+i);
|
|
set.add(domain.getMappedIndex(new DomainElement(i,taintType)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
@SuppressWarnings("unchecked")
|
|
public IntSet getTargets(int d1) {
|
|
//System.out.println(this.toString()+".getTargets("+d1+") "+bb);
|
|
//BitVectorIntSet set = new BitVectorIntSet();
|
|
MutableSparseIntSet set = MutableSparseIntSet.makeEmpty();
|
|
set.add(d1);
|
|
DomainElement de = domain.getMappedObject(d1);
|
|
if (de != null) {
|
|
addTargets(de.codeElement, set, de.taintSource);
|
|
}
|
|
return set;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public IUnaryFlowFunction getCallFlowFunction(
|
|
BasicBlockInContext<E> src,
|
|
BasicBlockInContext<E> dest,
|
|
BasicBlockInContext<E> ret) {
|
|
assert graph.isCall(src);
|
|
|
|
final SSAInvokeInstruction instruction = (SSAInvokeInstruction) src.getLastInstruction();
|
|
|
|
// String signature = dest.getMethod().getSignature();
|
|
// if ( dest.getMethod().isWalaSynthetic() ) {
|
|
// System.out.println("Synthetic: "+signature);
|
|
// } else {
|
|
// System.err.println(signature);
|
|
// }
|
|
|
|
|
|
// if ( LoaderUtils.fromLoader(src.getNode(), ClassLoaderReference.Application)
|
|
// && LoaderUtils.fromLoader(dest.getNode(), ClassLoaderReference.Primordial)) {
|
|
// System.out.println("Call to system: "+signature);
|
|
// }
|
|
|
|
// if (! dest.getMethod().isWalaSynthetic()
|
|
// && LoaderUtils.fromLoader(dest.getNode(), ClassLoaderReference.Primordial)) {
|
|
//
|
|
// MyLogger.log(DEBUG,"Primordial and No Summary! (getCallFlowFunction) - " + dest.getMethod().getReference());
|
|
// }
|
|
|
|
final Map<CodeElement,CodeElement> parameterMap = HashMapFactory.make();
|
|
for (int i = 0; i < instruction.getNumberOfPositionalParameters(); i++) {
|
|
Set<CodeElement> elements = CodeElement.valueElements(instruction.getUse(i));
|
|
for(CodeElement e: elements) {
|
|
parameterMap.put(e, new LocalElement(i+1));
|
|
}
|
|
}
|
|
|
|
return d1 -> {
|
|
BitVectorIntSet set = new BitVectorIntSet();
|
|
if(d1 == 0 || !(domain.getMappedObject(d1).codeElement instanceof LocalElement)) {
|
|
set.add(d1);
|
|
}
|
|
DomainElement de = domain.getMappedObject(d1);
|
|
if(de!=null && parameterMap.containsKey(de.codeElement))
|
|
set.add(domain.getMappedIndex(new DomainElement(parameterMap.get(de.codeElement),de.taintSource)));
|
|
return set;
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public IUnaryFlowFunction getCallNoneToReturnFlowFunction(
|
|
BasicBlockInContext<E> src,
|
|
BasicBlockInContext<E> dest) {
|
|
//I Believe this method is called only if there are no callees of src in the supergraph
|
|
//if supergraph included all primordials, this method can still be called if it calls a
|
|
//method that wasn't included in the scope
|
|
|
|
//Assertions.UNREACHABLE();
|
|
// TODO: Look up summary for this method, or warn if it doesn't exist.
|
|
assert (src.getNode().equals(dest.getNode()));
|
|
|
|
// final SSAInvokeInstruction instruction = (SSAInvokeInstruction) src.getLastInstruction();
|
|
|
|
// System.out.println("call to return(no callee) method inside call graph: " + src.getNode()+"--" + instruction.getDeclaredTarget());
|
|
// System.out.println("call to system: " + instruction.getDeclaredTarget());
|
|
return new DefUse(dest);
|
|
}
|
|
|
|
@Override
|
|
public IUnaryFlowFunction getCallToReturnFlowFunction(
|
|
BasicBlockInContext<E> src,
|
|
BasicBlockInContext<E> dest) {
|
|
assert (src.getNode().equals(dest.getNode()));
|
|
//final SSAInvokeInstruction instruction = (SSAInvokeInstruction) src.getLastInstruction();
|
|
//System.out.println("call to return method inside call graph: " + instruction.getDeclaredTarget());
|
|
|
|
return new DefUse(dest);
|
|
}
|
|
|
|
@Override
|
|
public IUnaryFlowFunction getNormalFlowFunction(
|
|
BasicBlockInContext<E> src,
|
|
BasicBlockInContext<E> dest) {
|
|
assert (src.getNode().equals(dest.getNode()));
|
|
//System.out.println("getNormalFlowFuntion");
|
|
//System.out.println("\tSrc " + src.getLastInstruction());
|
|
//System.out.println("\tDest " + dest.getLastInstruction());
|
|
return new DefUse(dest);
|
|
}
|
|
|
|
public class ReturnDefUse extends DefUse
|
|
{
|
|
CodeElement callSet;
|
|
Set<CodeElement> receivers = new HashSet<>();
|
|
|
|
public ReturnDefUse(BasicBlockInContext<E> dest,
|
|
BasicBlockInContext<E> call) {
|
|
super(dest);
|
|
|
|
// TODO: look into exception handling through getDef(1)
|
|
if(call.getLastInstruction() instanceof SSAInvokeInstruction) {
|
|
SSAInvokeInstruction invInst = (SSAInvokeInstruction) call.getLastInstruction();
|
|
if(!invInst.isSpecial()) {// && !invInst.isStatic()) {
|
|
// for (int i = 0; i < invInst.getNumberOfReturnValues(); i++) {
|
|
//
|
|
// }
|
|
if (invInst.hasDef()) {
|
|
callSet = new LocalElement(invInst.getReturnValue(0));
|
|
|
|
if ( !invInst.isStatic() ) {
|
|
//used to be invInst.getReceiver(), but I believe that was incorrect.
|
|
receivers.addAll(CodeElement.valueElements(invInst.getReceiver()));
|
|
//receivers.addAll(CodeElement.valueElements(pa, call.getNode(), invInst.getReturnValue(0)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
callSet = null;
|
|
}
|
|
// // TODO: look into exception handling through getDef(1)
|
|
// if(call.getLastInstruction().getNumberOfDefs() == 1)
|
|
// {
|
|
// //System.out.println("\treturn defines something: "+call.getLastInstruction());
|
|
// callSet = new LocalElement(call.getLastInstruction().getDef(0));
|
|
// if(call.getLastInstruction() instanceof SSAInvokeInstruction)
|
|
// {
|
|
// SSAInvokeInstruction invInst = (SSAInvokeInstruction) call.getLastInstruction();
|
|
// if(!invInst.isSpecial() && !invInst.isStatic()) {
|
|
// receivers.addAll(CodeElement.valueElements(pa, call.getNode(), invInst.getReceiver()));
|
|
// }
|
|
// }
|
|
// }
|
|
// else
|
|
// callSet = null;
|
|
}
|
|
|
|
@Override
|
|
public IntSet getTargets(int d1)
|
|
{
|
|
if(d1 != 0 && domain.getMappedObject(d1).codeElement instanceof ReturnElement)
|
|
{
|
|
BitVectorIntSet set = new BitVectorIntSet();
|
|
if(callSet != null) {
|
|
// System.out.println("callset: " + callSet);
|
|
set.add(domain.getMappedIndex(new DomainElement(callSet,domain.getMappedObject(d1).taintSource)));
|
|
}
|
|
return set;
|
|
}
|
|
else if(d1 != 0 && domain.getMappedObject(d1).codeElement instanceof LocalElement)
|
|
{
|
|
return new BitVectorIntSet();
|
|
}
|
|
else if(d1 != 0 && receivers.contains(domain.getMappedObject(d1).codeElement))
|
|
{
|
|
BitVectorIntSet set = new BitVectorIntSet();
|
|
if(callSet != null)
|
|
set.add(domain.getMappedIndex(new DomainElement(callSet,domain.getMappedObject(d1).taintSource)));
|
|
set.addAll(super.getTargets(d1));
|
|
return set;
|
|
}
|
|
else
|
|
{
|
|
return super.getTargets(d1);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public IFlowFunction getReturnFlowFunction(BasicBlockInContext<E> call,
|
|
BasicBlockInContext<E> src,
|
|
BasicBlockInContext<E> dest) {
|
|
assert (graph.isCall(call) && graph.isReturn(dest) && call.getNode().equals(dest.getNode()));
|
|
//final SSAInvokeInstruction instruction = (SSAInvokeInstruction) call.getLastInstruction();
|
|
|
|
//System.out.println("Return from call to method inside call graph: " + instruction.getDeclaredTarget());
|
|
|
|
return new ReturnDefUse(dest,call);
|
|
}
|
|
|
|
}
|