All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.infoflow.problems.BackwardsAliasProblem Maven / Gradle / Ivy

The newest version!
package soot.jimple.infoflow.problems;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import heros.FlowFunction;
import heros.FlowFunctions;
import heros.flowfunc.Identity;
import heros.flowfunc.KillAll;
import heros.solver.PathEdge;
import soot.ArrayType;
import soot.Local;
import soot.PrimType;
import soot.SootField;
import soot.SootMethod;
import soot.Type;
import soot.Unit;
import soot.Value;
import soot.jimple.ArrayRef;
import soot.jimple.AssignStmt;
import soot.jimple.BinopExpr;
import soot.jimple.CastExpr;
import soot.jimple.Constant;
import soot.jimple.DefinitionStmt;
import soot.jimple.FieldRef;
import soot.jimple.IdentityStmt;
import soot.jimple.InstanceFieldRef;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.InstanceOfExpr;
import soot.jimple.InvokeExpr;
import soot.jimple.NewArrayExpr;
import soot.jimple.ReturnStmt;
import soot.jimple.StaticFieldRef;
import soot.jimple.Stmt;
import soot.jimple.UnopExpr;
import soot.jimple.infoflow.InfoflowConfiguration;
import soot.jimple.infoflow.InfoflowManager;
import soot.jimple.infoflow.aliasing.Aliasing;
import soot.jimple.infoflow.callmappers.CallerCalleeManager;
import soot.jimple.infoflow.callmappers.ICallerCalleeArgumentMapper;
import soot.jimple.infoflow.cfg.FlowDroidSinkStatement;
import soot.jimple.infoflow.cfg.FlowDroidSourceStatement;
import soot.jimple.infoflow.collect.MutableTwoElementSet;
import soot.jimple.infoflow.data.Abstraction;
import soot.jimple.infoflow.data.AccessPath;
import soot.jimple.infoflow.handlers.TaintPropagationHandler;
import soot.jimple.infoflow.problems.rules.EmptyPropagationRuleManagerFactory;
import soot.jimple.infoflow.solver.functions.SolverCallFlowFunction;
import soot.jimple.infoflow.solver.functions.SolverCallToReturnFlowFunction;
import soot.jimple.infoflow.solver.functions.SolverNormalFlowFunction;
import soot.jimple.infoflow.solver.functions.SolverReturnFlowFunction;
import soot.jimple.infoflow.typing.TypeUtils;
import soot.jimple.infoflow.util.BaseSelector;

/**
 * Class which contains the alias analysis for the backwards analysis.
 *
 * @author Tim Lange
 */
public class BackwardsAliasProblem extends AbstractInfoflowProblem {
	private final static boolean DEBUG_PRINT = false;

	public BackwardsAliasProblem(InfoflowManager manager) {
		super(manager, null, EmptyPropagationRuleManagerFactory.INSTANCE);
	}

	@Override
	protected FlowFunctions createFlowFunctionsFactory() {
		return new FlowFunctions() {
			private Abstraction checkAbstraction(Abstraction abs) {
				if (abs == null)
					return null;

				// Primitive types and strings cannot have aliases and thus
				// never need to be propagated back
				if (!abs.getAccessPath().isStaticFieldRef()) {
					if (abs.getAccessPath().getBaseType() instanceof PrimType)
						return null;
				} else {
					if (abs.getAccessPath().getFirstFieldType() instanceof PrimType)
						return null;
				}
				return abs;
			}

			@Override
			public FlowFunction getNormalFlowFunction(Unit srcUnit, Unit destUnit) {
				if (!(srcUnit instanceof DefinitionStmt))
					return Identity.v();

				final DefinitionStmt defStmt = (DefinitionStmt) srcUnit;

				return new SolverNormalFlowFunction() {
					@Override
					public Set computeTargets(Abstraction d1, Abstraction source) {
						if (source == getZeroValue())
							return null;
						assert !source.getAccessPath().isEmpty();

						if (taintPropagationHandler != null)
							taintPropagationHandler.notifyFlowIn(srcUnit, source, manager,
									TaintPropagationHandler.FlowFunctionType.NormalFlowFunction);

						// TurnUnit is the sink. Below this stmt, the taint is not valid anymore
						// Therefore we turn around here.
						if (source.getTurnUnit() == srcUnit) {
							return notifyOutFlowHandlers(srcUnit, d1, source, null,
									TaintPropagationHandler.FlowFunctionType.NormalFlowFunction);
						}

						Set res = computeAliases(defStmt, d1, source);
						if (DEBUG_PRINT)
							System.out.println("Alias Normal" + "\n" + "In: " + source.toString() + "\n" + "Stmt: "
									+ srcUnit.toString() + "\n" + "Out: " + (res == null ? "[]" : res.toString()) + "\n"
									+ "---------------------------------------");

						return notifyOutFlowHandlers(srcUnit, d1, source, res,
								TaintPropagationHandler.FlowFunctionType.NormalFlowFunction);
					}

					private Set computeAliases(final DefinitionStmt defStmt, Abstraction d1,
							Abstraction source) {
						if (defStmt instanceof IdentityStmt)
							return Collections.singleton(source);
						if (!(defStmt instanceof AssignStmt))
							return null;

						MutableTwoElementSet res = new MutableTwoElementSet<>();
						final AssignStmt assignStmt = (AssignStmt) defStmt;
						final Value leftOp = assignStmt.getLeftOp();
						final Value rightOp = assignStmt.getRightOp();
						final Value leftVal = BaseSelector.selectBase(leftOp, false);
						final Value rightVal = BaseSelector.selectBase(rightOp, false);

						AccessPath ap = source.getAccessPath();
						Value sourceBase = ap.getPlainValue();
						Type rightType = rightOp.getType();
						boolean handoverLeftValue = false;
						boolean cutSubfield = false;
						boolean leftSideOverwritten = false;
						if (leftOp instanceof StaticFieldRef) {
							if (manager.getConfig()
									.getStaticFieldTrackingMode() != InfoflowConfiguration.StaticFieldTrackingMode.None
									&& ap.firstFieldMatches(((StaticFieldRef) leftOp).getField())) {
								handoverLeftValue = true;
								cutSubfield = true;
							}
						} else if (leftOp instanceof InstanceFieldRef) {
							InstanceFieldRef instRef = (InstanceFieldRef) leftOp;

							// base matches
							if (instRef.getBase() == sourceBase) {
								AccessPath mappedAp = Aliasing.getReferencedAPBase(ap,
										new SootField[] { instRef.getField() }, manager);
								if (mappedAp != null) {
									handoverLeftValue = true;
									cutSubfield = true;
									if (!mappedAp.equals(ap))
										ap = mappedAp;
								}
							}
						} else if (leftVal == sourceBase) {
							// Either the alias is overwritten here or a write to an array element
							handoverLeftValue = leftOp instanceof ArrayRef
									&& ap.getArrayTaintType() != AccessPath.ArrayTaintType.Length;
							leftSideOverwritten = !handoverLeftValue;
						}

						if (handoverLeftValue) {
							Abstraction newAbs = null;
							if (rightVal instanceof Constant) {
								if (manager.getConfig().getImplicitFlowMode().trackControlFlowDependencies()) {
									newAbs = source.deriveConditionalUpdate(assignStmt);
									for (Unit pred : manager.getICFG().getPredsOf(srcUnit))
										handOver(d1, pred, newAbs);
								}
							} else {
								AccessPath newAp = manager.getAccessPathFactory().copyWithNewValue(ap, rightOp,
										rightType, cutSubfield);
								newAbs = source.deriveNewAbstraction(newAp, assignStmt);
							}

							if (newAbs != null && !newAbs.equals(source)) {
								// We found a missed path upwards
								// inject same stmt in infoflow solver
								for (Unit pred : manager.getICFG().getPredsOf(srcUnit))
									handOver(d1, pred, newAbs);
							}
						}

						if (leftSideOverwritten)
							return null;
						res.add(source);

						// BinopExr & UnopExpr operands can not have aliases
						// as both only can have primitives on the right side
						// NewArrayExpr do not produce new aliases
						if (rightOp instanceof BinopExpr || rightOp instanceof UnopExpr
								|| rightOp instanceof NewArrayExpr)
							return res;

						boolean localAliases = (leftOp instanceof Local || leftOp instanceof ArrayRef)
								&& !(leftOp.getType() instanceof PrimType);
						boolean fieldAliases = leftOp instanceof FieldRef
								&& !(((FieldRef) leftOp).getField().getType() instanceof PrimType);
						if ((localAliases || fieldAliases) && !(rightVal.getType() instanceof PrimType)) {
							boolean addLeftValue = false;
							boolean cutFirstFieldLeft = false;
							Type leftType = null;
							boolean createNewVal = false;

							if (rightVal instanceof StaticFieldRef) {
								if (manager.getConfig()
										.getStaticFieldTrackingMode() != InfoflowConfiguration.StaticFieldTrackingMode.None
										&& ap.firstFieldMatches(((StaticFieldRef) rightVal).getField())) {
									addLeftValue = true;
								}
							} else if (rightVal instanceof InstanceFieldRef) {
								InstanceFieldRef instRef = (InstanceFieldRef) rightVal;

								if (instRef.getBase() == sourceBase && ap.isInstanceFieldRef()) {
									AccessPath mappedAp = Aliasing.getReferencedAPBase(ap,
											new SootField[] { instRef.getField() }, manager);
									if (mappedAp != null) {
										addLeftValue = true;
										cutFirstFieldLeft = true;
										if (!mappedAp.equals(ap)) {
											ap = mappedAp;
											source = source.deriveNewAbstraction(mappedAp, null);
										}
									}
								}
							} else if (rightVal == sourceBase) {
								addLeftValue = true;
								leftType = ap.getBaseType();
								// We did not keep the ArrayRef, so rightVal is already the array base
								if (rightOp instanceof ArrayRef) {
									leftType = ((ArrayType) leftType).getElementType();
								} else if (leftOp instanceof ArrayRef) {
									ArrayRef arrayRef = (ArrayRef) leftOp;
									leftType = TypeUtils.buildArrayOrAddDimension(leftType,
											arrayRef.getType().getArrayType());
								} else {
									if (!manager.getTypeUtils().checkCast(source.getAccessPath().getBaseType(),
											leftOp.getType()))
										return null;
								}

								// LengthExpr extends UnopExpr, not possible here
								if (rightVal instanceof CastExpr) {
									CastExpr ce = (CastExpr) rightOp;
									if (!manager.getHierarchy().canStoreType(leftType, ce.getCastType()))
										leftType = ce.getCastType();
								} else if (rightVal instanceof InstanceOfExpr) {
									// We could just produce a boolean, which won't be tracked anyways
									addLeftValue = false;
								}
							}

							if (addLeftValue) {
								AccessPath newAp;
								if (createNewVal)
									newAp = manager.getAccessPathFactory().createAccessPath(leftVal, true);
								else
									newAp = manager.getAccessPathFactory().copyWithNewValue(ap, leftOp, leftType,
											cutFirstFieldLeft);
								Abstraction newAbs = checkAbstraction(source.deriveNewAbstraction(newAp, assignStmt));
								if (newAbs != null && newAbs != source) {
									if (rightVal instanceof StaticFieldRef && manager.getConfig()
											.getStaticFieldTrackingMode() == InfoflowConfiguration.StaticFieldTrackingMode.ContextFlowInsensitive)
										manager.getGlobalTaintManager().addToGlobalTaintState(newAbs);
									else {
										res.add(newAbs);
									}
								}
							}
						}

						return res;
					}
				};
			}

			@Override
			public FlowFunction getCallFlowFunction(final Unit callSite, final SootMethod dest) {
				if (!dest.hasActiveBody()) {
					logger.debug("Call skipped because target has no body: {} -> {}", callSite, dest);
					return KillAll.v();
				}

				if (!(callSite instanceof Stmt))
					return KillAll.v();

				final Stmt callStmt = (Stmt) callSite;
				final InvokeExpr ie = callStmt.containsInvokeExpr() ? callStmt.getInvokeExpr() : null;

				final Local[] paramLocals = dest.getActiveBody().getParameterLocals().toArray(new Local[0]);
				final Local thisLocal = dest.isStatic() ? null : dest.getActiveBody().getThisLocal();

				final boolean isSink = callStmt.hasTag(FlowDroidSinkStatement.TAG_NAME);
				final boolean isSource = callStmt.hasTag(FlowDroidSourceStatement.TAG_NAME);

				final ICallerCalleeArgumentMapper mapper = CallerCalleeManager.getMapper(manager, callStmt, dest);
				final boolean isReflectiveCallSite = mapper != null ? mapper.isReflectiveMapper() : false;

				return new SolverCallFlowFunction() {
					@Override
					public Set computeTargets(Abstraction d1, Abstraction source) {
						if (source == getZeroValue())
							return null;

						// Notify the handler if we have one
						if (taintPropagationHandler != null)
							taintPropagationHandler.notifyFlowIn(callStmt, source, manager,
									TaintPropagationHandler.FlowFunctionType.CallFlowFunction);

						// TurnUnit is the sink. Below this stmt, the taint is not valid anymore
						// Therefore we turn around here.
						if (source.getTurnUnit() == callSite) {
							return notifyOutFlowHandlers(callSite, d1, source, null,
									TaintPropagationHandler.FlowFunctionType.CallFlowFunction);
						}

						Set res = computeTargetsInternal(d1, source);
						if (DEBUG_PRINT)
							System.out.println("Alias Call" + "\n" + "In: " + source.toString() + "\n" + "Stmt: "
									+ callStmt.toString() + "\n" + "Out: " + (res == null ? "[]" : res.toString())
									+ "\n" + "---------------------------------------");

						return notifyOutFlowHandlers(callStmt, d1, source, res,
								TaintPropagationHandler.FlowFunctionType.CallFlowFunction);
					}

					private Set computeTargetsInternal(Abstraction d1, Abstraction source) {
						if (!manager.getConfig().getInspectSources() && isSource)
							return null;
						if (!manager.getConfig().getInspectSinks() && isSink)
							return null;
						if (manager.getConfig()
								.getStaticFieldTrackingMode() == InfoflowConfiguration.StaticFieldTrackingMode.None
								&& dest.isStaticInitializer())
							return null;
						if (isExcluded(dest))
							return null;
						if (taintWrapper != null && taintWrapper.isExclusive(callStmt, source))
							return null;

						if (manager.getConfig()
								.getStaticFieldTrackingMode() != InfoflowConfiguration.StaticFieldTrackingMode.None
								&& source.getAccessPath().isStaticFieldRef()) {
							if (!interproceduralCFG().isStaticFieldRead(dest, source.getAccessPath().getFirstField()))
								return null;
						}

						HashSet res = new HashSet<>();

						if (manager.getConfig()
								.getStaticFieldTrackingMode() != InfoflowConfiguration.StaticFieldTrackingMode.None
								&& source.getAccessPath().isStaticFieldRef()) {
							Abstraction abs = checkAbstraction(
									source.deriveNewAbstraction(source.getAccessPath(), callStmt));
							if (abs != null)
								res.add(abs);
						}

						// map o to this
						if (!source.getAccessPath().isStaticFieldRef() && !dest.isStatic()) {
							Value callBase = mapper.getCallerValueOfCalleeParameter(ie,
									ICallerCalleeArgumentMapper.BASE_OBJECT);

							if (callBase != null) {
								Value sourceBase = source.getAccessPath().getPlainValue();
								if (callBase == sourceBase && manager.getTypeUtils()
										.hasCompatibleTypesForCall(source.getAccessPath(), dest.getDeclaringClass())) {
									if (isReflectiveCallSite || !hasAnotherReferenceOnBase(ie, sourceBase,
											mapper.getCallerIndexOfCalleeParameter(
													ICallerCalleeArgumentMapper.BASE_OBJECT))) {
										AccessPath ap = manager.getAccessPathFactory()
												.copyWithNewValue(source.getAccessPath(), thisLocal);
										Abstraction abs = checkAbstraction(
												source.deriveNewAbstraction(ap, (Stmt) callSite));
										if (abs != null)
											res.add(abs);
									}
								}
							}
						}

						// map arguments to parameter
						if (ie != null && dest.getParameterCount() > 0) {
							for (int i = 0; i < ie.getArgCount(); i++) {
								if (ie.getArg(i) != source.getAccessPath().getPlainValue())
									continue;

								int mappedIndex = mapper.getCalleeIndexOfCallerParameter(i);
								if (mappedIndex == ICallerCalleeArgumentMapper.UNKNOWN)
									continue;

								// taint all parameters if reflective call site
								if (mappedIndex == ICallerCalleeArgumentMapper.ALL_PARAMS) {
									for (Value param : paramLocals) {
										AccessPath ap = manager.getAccessPathFactory()
												.copyWithNewValue(source.getAccessPath(), param, null, false);
										Abstraction abs = checkAbstraction(source.deriveNewAbstraction(ap, callStmt));
										if (abs != null)
											res.add(abs);
									}
									// taint just the tainted parameter
								} else {
									AccessPath ap = manager.getAccessPathFactory()
											.copyWithNewValue(source.getAccessPath(), paramLocals[i]);
									Abstraction abs = checkAbstraction(source.deriveNewAbstraction(ap, callStmt));
									if (abs != null)
										res.add(abs);
								}
							}
						}

						for (Abstraction d3 : res)
							manager.getMainSolver().injectContext(solver, dest, d3, callSite, source, d1);

						return res;
					}
				};
			}

			@Override
			public FlowFunction getReturnFlowFunction(Unit callSite, SootMethod callee, Unit exitStmt,
					Unit returnSite) {
				if (callSite != null && !(callSite instanceof Stmt))
					return KillAll.v();

				final Value[] paramLocals = new Value[callee.getParameterCount()];
				for (int i = 0; i < callee.getParameterCount(); i++)
					paramLocals[i] = callee.getActiveBody().getParameterLocal(i);

				final Stmt callStmt = (Stmt) callSite;
				final InvokeExpr ie = (callStmt != null && callStmt.containsInvokeExpr()) ? callStmt.getInvokeExpr()
						: null;
				final ReturnStmt returnStmt = (exitStmt instanceof ReturnStmt) ? (ReturnStmt) exitStmt : null;

				final Local thisLocal = callee.isStatic() ? null : callee.getActiveBody().getThisLocal();
				final ICallerCalleeArgumentMapper mapper = CallerCalleeManager.getMapper(manager, callStmt, callee);
				final boolean isReflectiveCallSite = mapper != null ? mapper.isReflectiveMapper() : false;

				return new SolverReturnFlowFunction() {
					@Override
					public Set computeTargets(Abstraction source, Abstraction calleeD1,
							Collection callerD1s) {
						if (source == getZeroValue())
							return null;
						if (callSite == null)
							return null;

						if (taintPropagationHandler != null)
							taintPropagationHandler.notifyFlowIn(callStmt, source, manager,
									TaintPropagationHandler.FlowFunctionType.ReturnFlowFunction);

						// TurnUnit is the sink. Below this stmt, the taint is not valid anymore
						// Therefore we turn around here.
						if (source.getTurnUnit() == callSite) {
							return notifyOutFlowHandlers(callSite, calleeD1, source, null,
									TaintPropagationHandler.FlowFunctionType.ReturnFlowFunction);
						}

						Set res = computeTargetsInternal(source);
						if (DEBUG_PRINT)
							System.out.println("Alias Return" + "\n" + "In: " + source.toString() + "\n" + "Stmt: "
									+ callSite.toString() + "\n" + "Out: " + (res == null ? "[]" : res.toString())
									+ "\n" + "---------------------------------------");

						return notifyOutFlowHandlers(exitStmt, calleeD1, source, res,
								TaintPropagationHandler.FlowFunctionType.ReturnFlowFunction);
					}

					private Set computeTargetsInternal(Abstraction source) {
						HashSet res = new HashSet<>();

						// Static fields get propagated unchanged
						if (manager.getConfig()
								.getStaticFieldTrackingMode() != InfoflowConfiguration.StaticFieldTrackingMode.None
								&& source.getAccessPath().isStaticFieldRef()) {
							res.add(source);
							return res;
						}

						// x = o.m()
						if (returnStmt != null && callStmt instanceof AssignStmt) {
							Value retLocal = returnStmt.getOp();
							DefinitionStmt defnStmt = (DefinitionStmt) callSite;
							Value leftOp = defnStmt.getLeftOp();

							if (retLocal == source.getAccessPath().getPlainValue() && !isExceptionHandler(returnSite)) {
								AccessPath ap = manager.getAccessPathFactory().copyWithNewValue(source.getAccessPath(),
										leftOp);
								Abstraction abs = checkAbstraction(source.deriveNewAbstraction(ap, (Stmt) exitStmt));
								if (abs != null) {
									res.add(abs);
								}
							}
						}

						// o.m(a1, ..., an)
						// map o.f to this.f
						if (!callee.isStatic()) {
							Value sourceBase = source.getAccessPath().getPlainValue();
							if (thisLocal == sourceBase && manager.getTypeUtils()
									.hasCompatibleTypesForCall(source.getAccessPath(), callee.getDeclaringClass())) {
								Value callBase = mapper.getCallerValueOfCalleeParameter(ie,
										ICallerCalleeArgumentMapper.BASE_OBJECT);

								if (callBase != null) {
									if (isReflectiveCallSite || !hasAnotherReferenceOnBase(ie, sourceBase,
											mapper.getCallerIndexOfCalleeParameter(
													ICallerCalleeArgumentMapper.BASE_OBJECT))) {
										AccessPath ap = manager.getAccessPathFactory().copyWithNewValue(
												source.getAccessPath(), callBase,
												isReflectiveCallSite ? null : source.getAccessPath().getBaseType(),
												false);
										Abstraction abs = checkAbstraction(
												source.deriveNewAbstraction(ap, (Stmt) exitStmt));
										if (abs != null) {
											res.add(abs);
										}
									}
								}
							}
						}

						// map arguments to parameter
						if (ie != null) {
							for (int i = 0; i < callee.getParameterCount(); i++) {
								if (source.getAccessPath().getPlainValue() != paramLocals[i])
									continue;
								if (isPrimitiveOrStringBase(source))
									continue;

								Value originalCallArg = mapper.getCallerValueOfCalleeParameter(ie, i);
								if (originalCallArg == null)
									continue;
								if (callSite instanceof DefinitionStmt && !isExceptionHandler(returnSite)) {
									DefinitionStmt defnStmt = (DefinitionStmt) callSite;
									Value leftOp = defnStmt.getLeftOp();
									originalCallArg = defnStmt.getInvokeExpr().getArg(i);
									if (originalCallArg == leftOp)
										continue;
								}

								if (interproceduralCFG().methodWritesValue(callee, paramLocals[i]))
									continue;

								if (!AccessPath.canContainValue(originalCallArg))
									continue;
								if (!isReflectiveCallSite && !manager.getTypeUtils().checkCast(source.getAccessPath(),
										originalCallArg.getType()))
									continue;

								AccessPath ap = manager.getAccessPathFactory().copyWithNewValue(source.getAccessPath(),
										originalCallArg,
										isReflectiveCallSite ? null : source.getAccessPath().getBaseType(), false);
								Abstraction abs = checkAbstraction(source.deriveNewAbstraction(ap, (Stmt) exitStmt));
								if (abs != null) {
									res.add(abs);
								}
							}
						}

						if (res.isEmpty()) {
							return null;
						} else {
							for (Abstraction abs : res) {
								if (abs != source) {
									abs.setCorrespondingCallSite((Stmt) callSite);
								}
							}
						}

						return res;
					}
				};
			}

			@Override
			public FlowFunction getCallToReturnFlowFunction(Unit callSite, Unit returnSite) {
				if (!(callSite instanceof Stmt)) {
					return KillAll.v();
				}

				final Stmt callStmt = (Stmt) callSite;
				final InvokeExpr invExpr = callStmt.getInvokeExpr();

				final Value[] callArgs = new Value[invExpr.getArgCount()];
				for (int i = 0; i < invExpr.getArgCount(); i++) {
					callArgs[i] = invExpr.getArg(i);
				}

				final SootMethod callee = invExpr.getMethod();

				final boolean isSource = manager.getSourceSinkManager() != null
						&& manager.getSourceSinkManager().getSourceInfo(callStmt, manager) != null;

				return new SolverCallToReturnFlowFunction() {
					@Override
					public Set computeTargets(Abstraction d1, Abstraction source) {
						if (source == getZeroValue())
							return null;

						// Notify the handler if we have one
						if (taintPropagationHandler != null)
							taintPropagationHandler.notifyFlowIn(callSite, source, manager,
									TaintPropagationHandler.FlowFunctionType.CallToReturnFlowFunction);

						// TurnUnit is the sink. Below this stmt, the taint is not valid anymore
						// Therefore we turn around here.
						if (source.getTurnUnit() != null && (source.getTurnUnit() == callSite
								|| manager.getICFG().getCalleesOfCallAt(callSite).stream()
										.anyMatch(m -> manager.getICFG().getMethodOf(source.getTurnUnit()) == m))) {

							return notifyOutFlowHandlers(callSite, d1, source, null,
									TaintPropagationHandler.FlowFunctionType.CallToReturnFlowFunction);
						}

						Set res = computeTargetsInternal(d1, source);
						if (DEBUG_PRINT)
							System.out.println("Alias CallToReturn" + "\n" + "In: " + source.toString() + "\n"
									+ "Stmt: " + callStmt.toString() + "\n" + "Out: "
									+ (res == null ? "[]" : res.toString()) + "\n"
									+ "---------------------------------------");

						return notifyOutFlowHandlers(callSite, d1, source, res,
								TaintPropagationHandler.FlowFunctionType.CallToReturnFlowFunction);
					}

					private Set computeTargetsInternal(Abstraction d1, Abstraction source) {
						if (taintWrapper != null) {
							if (taintWrapper.isExclusive(callStmt, source)) {
								handOver(d1, callSite, source);
							}

							Set wrapperAliases = taintWrapper.getAliasesForMethod(callStmt, d1, source);
							if (wrapperAliases != null && !wrapperAliases.isEmpty()) {
								Set passOnSet = new HashSet<>(wrapperAliases.size());
								for (Abstraction abs : wrapperAliases) {
									passOnSet.add(abs);
									if (abs != source)
										abs.setCorrespondingCallSite(callStmt);

									for (Unit u : manager.getICFG().getPredsOf(callSite))
										handOver(d1, u, abs);
								}
								return passOnSet;
							}
						}

						// If excluded or we do not anything about the callee,
						// we just pass the taint over the statement
						if (interproceduralCFG().getCalleesOfCallAt(callSite).isEmpty()) {
							return Collections.singleton(source);
						}

						if (isExcluded(callee)) {
							return Collections.singleton(source);
						}

						// If static field is used, we do not pass it over
						if (manager.getConfig()
								.getStaticFieldTrackingMode() != InfoflowConfiguration.StaticFieldTrackingMode.None
								&& source.getAccessPath().isStaticFieldRef() && interproceduralCFG()
										.isStaticFieldUsed(callee, source.getAccessPath().getFirstField())) {
							return null;
						}

						// See stringBuilderTest5. original needs to pass over arraycopy.
						if (!callee.isNative()) {
							// Do not pass tainted base over the statement
							if (callStmt.getInvokeExpr() instanceof InstanceInvokeExpr) {
								InstanceInvokeExpr inv = (InstanceInvokeExpr) callStmt.getInvokeExpr();
								if (inv.getBase() == source.getAccessPath().getPlainValue())
									return null;
							}

							// Do not pass over reference parameters
							// CallFlow passes this into the callee
							if (Arrays.stream(callArgs).anyMatch(arg -> !isPrimitiveOrStringBase(source)
									&& arg == source.getAccessPath().getPlainValue())) {
								// non standard source sink manager might need this
								if (isSource)
									handOver(d1, callSite, source);
								return null;
							}
						} else {
							for (Value arg : callArgs) {
								if (arg == source.getAccessPath().getPlainValue()) {
									// well, this is sorta a mix of infoflow and alias search
									// if we find an alias above, which is the an argument of arraycopy,
									// the native stmt does not create a new alias but we notice that we
									// missed this argument in the infoflow search.
									Abstraction newSource = source.deriveNewAbstractionWithTurnUnit(callSite);
									handOver(d1, callSite, newSource);
									return null;
								}
							}
						}

						return Collections.singleton(source);
					}
				};
			}

			private boolean isPrimitiveOrStringBase(Abstraction abs) {
				Type t = abs.getAccessPath().getBaseType();
				return t instanceof PrimType
						|| (TypeUtils.isStringType(t) && !abs.getAccessPath().getCanHaveImmutableAliases());
			}

			private void handOver(Abstraction d1, Unit unit, Abstraction in) {
				in = in.getActiveCopy();

				if (manager.getConfig().getImplicitFlowMode().trackControlFlowDependencies()) {
					// We maybe turned around inside a conditional, so we reconstruct the condition
					// dominator. Also, we lost track of the dominators in the alias search. Thus,
					// we derive interprocedural wildcards.
					// See ImplicitTests#conditionalAliasingTest
					List condUnits = manager.getOriginalICFG().getConditionalBranchesInterprocedural(unit);
					// No condition path -> no need to search for one
					for (Unit condUnit : condUnits) {
						Abstraction abs = in.deriveNewAbstractionWithDominator(condUnit);
						if (abs != null)
							manager.getMainSolver().processEdge(new PathEdge<>(d1, unit, abs));
					}
				} else {
					manager.getMainSolver().processEdge(new PathEdge<>(d1, unit, in));
				}
			}
		};
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy