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

soot.jimple.infoflow.methodSummary.data.sourceSink.AbstractFlowSinkSource Maven / Gradle / Ivy

package soot.jimple.infoflow.methodSummary.data.sourceSink;

import java.util.HashMap;
import java.util.Map;

import soot.Local;
import soot.Value;
import soot.jimple.AssignStmt;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.InvokeExpr;
import soot.jimple.Stmt;
import soot.jimple.infoflow.methodSummary.data.summary.GapDefinition;
import soot.jimple.infoflow.methodSummary.data.summary.SourceSinkType;
import soot.jimple.infoflow.methodSummary.taintWrappers.AccessPathFragment;
import soot.jimple.infoflow.methodSummary.xml.XMLConstants;

/**
 * Data class which stores the data associated to a Sink or a Source of a method
 * flow.
 */
public abstract class AbstractFlowSinkSource {
	protected final SourceSinkType type;
	protected final int parameterIdx;
	protected final String baseType;
	protected final AccessPathFragment accessPath;
	protected final GapDefinition gap;
	protected final Object userData;
	protected final boolean matchStrict;
	protected ConstraintType isConstrained;


	public AbstractFlowSinkSource(SourceSinkType type, int parameterIdx, String baseType, AccessPathFragment accessPath,
								  boolean matchStrict, ConstraintType isConstrained) {
		this(type, parameterIdx, baseType, accessPath, null, matchStrict, isConstrained);
	}

	public AbstractFlowSinkSource(SourceSinkType type, String baseType, AccessPathFragment accessPath,
								  GapDefinition gap, boolean matchStrict, ConstraintType isConstrained) {
		this(type, -1, baseType, accessPath, gap, matchStrict, isConstrained);
	}

	public AbstractFlowSinkSource(SourceSinkType type, int parameterIdx, String baseType, AccessPathFragment accessPath,
								  GapDefinition gap, boolean matchStrict, ConstraintType isConstrained) {
		this(type, parameterIdx, baseType, accessPath, gap, null, matchStrict, isConstrained);
	}

	public AbstractFlowSinkSource(SourceSinkType type, int parameterIdx, String baseType, AccessPathFragment accessPath,
								  GapDefinition gap, Object userData, boolean matchStrict, ConstraintType isConstrained) {
		this.type = type;
		this.parameterIdx = parameterIdx;
		this.baseType = baseType;
		this.accessPath = accessPath;
		this.gap = gap;
		this.userData = userData;
		this.matchStrict = matchStrict;
		this.isConstrained = isConstrained;
	}


	/**
	 * Checks whether the current source or sink is coarser than the given one,
	 * i.e., if all elements referenced by the given source or sink are also
	 * referenced by this one
	 * 
	 * @param other The source or sink with which to compare the current one
	 * @return True if the current source or sink is coarser than the given one,
	 *         otherwise false
	 */
	public boolean isCoarserThan(AbstractFlowSinkSource other) {
		if (this.equals(other))
			return true;

		if (this.type != other.type || this.parameterIdx != other.parameterIdx
				|| !safeCompare(this.baseType, other.baseType) || !safeCompare(this.gap, other.gap))
			return false;
		if (this.accessPath != null && other.accessPath != null) {
			if (this.accessPath.length() > other.accessPath.length())
				return false;
			for (int i = 0; i < this.accessPath.length(); i++)
				if (!this.accessPath.getField(i).equals(other.accessPath.getField(i)))
					return false;
		}
		return true;
	}

	public boolean isParameter() {
		return type == SourceSinkType.Parameter;
	}

	public boolean isThis() {
		return type == SourceSinkType.Field && !hasAccessPath();
	}

	public boolean isCustom() {
		return type == SourceSinkType.Custom;
	}

	public int getParameterIndex() {
		return parameterIdx;
	}

	public String getBaseType() {
		return baseType;
	}

	/**
	 * Gets whether this taint is on a *base* field. Note that this does not include
	 * fields starting on parameters or return values.
	 * 
	 * @return True if this taint references a base field, false otherwise
	 */
	public boolean isField() {
		return type == SourceSinkType.Field;
	}

	public AccessPathFragment getAccessPath() {
		return accessPath;
	}

	public boolean isReturn() {
		return type == SourceSinkType.Return;
	}

	public boolean isGapBaseObject() {
		return type == SourceSinkType.GapBaseObject;
	}

	public boolean hasAccessPath() {
		return accessPath != null && !accessPath.isEmpty();
	}

	public int getAccessPathLength() {
		return accessPath == null ? 0 : accessPath.length();
	}

	public SourceSinkType getType() {
		return this.type;
	}

	public GapDefinition getGap() {
		return this.gap;
	}

	public boolean hasGap() {
		return this.gap != null;
	}

	public String getLastFieldType() {
		if (accessPath == null || accessPath.isEmpty())
			return baseType;
		return accessPath.getLastFieldType();
	}

	/**
	 * Gets whether strict access path matching shall be applied to this source
	 * definition. Strict matching means that a taint on a.* does NOT match a source
	 * defined for a.foo.
	 * 
	 * @return True if strict access path matching shall be applied, otherwise false
	 */
	public boolean isMatchStrict() {
		return matchStrict;
	}

	public boolean isConstrained() {
		return isConstrained == ConstraintType.TRUE || isConstrained == ConstraintType.NO_MATCH;
	}

	public boolean shiftRight() {
		return isConstrained == ConstraintType.SHIFT_RIGHT;
	}

	public boolean shiftLeft() {
		return isConstrained == ConstraintType.SHIFT_LEFT;
	}

	public boolean anyShift() {
		return shiftLeft() || shiftRight();
	}

	public boolean keepConstraint() {
		return isConstrained == ConstraintType.KEEP;
	}

	public boolean keepOnRO() {
		return isConstrained == ConstraintType.READONLY;
	}

	public boolean append() { return isConstrained == ConstraintType.APPEND; }

	public ConstraintType getConstraintType() {
		return isConstrained;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((accessPath == null) ? 0 : accessPath.hashCode());
		result = prime * result + ((baseType == null) ? 0 : baseType.hashCode());
		result = prime * result + ((gap == null) ? 0 : gap.hashCode());
		result = prime * result + (matchStrict ? 1231 : 1237);
		result = prime * result + isConstrained.hashCode();
		result = prime * result + parameterIdx;
		result = prime * result + ((type == null) ? 0 : type.hashCode());
		result = prime * result + ((userData == null) ? 0 : userData.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AbstractFlowSinkSource other = (AbstractFlowSinkSource) obj;
		if (accessPath == null) {
			if (other.accessPath != null)
				return false;
		} else if (!accessPath.equals(other.accessPath))
			return false;
		if (baseType == null) {
			if (other.baseType != null)
				return false;
		} else if (!baseType.equals(other.baseType))
			return false;
		if (gap == null) {
			if (other.gap != null)
				return false;
		} else if (!gap.equals(other.gap))
			return false;
		if (matchStrict != other.matchStrict)
			return false;
		if (isConstrained != other.isConstrained)
			return false;
		if (parameterIdx != other.parameterIdx)
			return false;
		if (type != other.type)
			return false;
		if (userData == null) {
			if (other.userData != null)
				return false;
		} else if (!userData.equals(other.userData))
			return false;
		return true;
	}

	protected boolean safeCompare(Object o1, Object o2) {
		if (o1 == null)
			return o2 == null;
		if (o2 == null)
			return o1 == null;
		return o1.equals(o2);
	}

	public Map xmlAttributes() {
		Map res = new HashMap();
		if (isParameter()) {
			res.put(XMLConstants.ATTRIBUTE_FLOWTYPE, XMLConstants.VALUE_PARAMETER);
			res.put(XMLConstants.ATTRIBUTE_PARAMETER_INDEX, getParameterIndex() + "");
		} else if (isField())
			res.put(XMLConstants.ATTRIBUTE_FLOWTYPE, XMLConstants.VALUE_FIELD);
		else if (isReturn())
			res.put(XMLConstants.ATTRIBUTE_FLOWTYPE, XMLConstants.VALUE_RETURN);
		else
			throw new RuntimeException("Invalid source type");

		if (baseType != null)
			res.put(XMLConstants.ATTRIBUTE_BASETYPE, baseType);
		if (hasAccessPath())
			res.put(XMLConstants.ATTRIBUTE_ACCESSPATH, getAccessPath().toString());
		if (gap != null)
			res.put(XMLConstants.ATTRIBUTE_GAP, getGap().getID() + "");

		return res;
	}

	/**
	 * Gets the custom user data associated with this sink
	 * 
	 * @return The custom user data associated with this sink
	 */
	public Object getUserData() {
		return this.userData;
	}

	/**
	 * Replaces the gaps in this definition according to the given map
	 * 
	 * @param replacementMap A mapping from gap id to new gap data object
	 * @return A copy of this definition in which the gaps that also occur in the
	 *         given map have been replaced with the values from the map
	 */
	public abstract AbstractFlowSinkSource replaceGaps(Map replacementMap);

	/**
	 * Gets the base local for the access path that this source or sink definition
	 * references
	 * 
	 * @param stmt The context in which to map the definition to concrete locals
	 * @return The local that resembles the base local of this source or sink
	 *         definition in the given context or null if this
	 *         definition is not valid in the given context
	 */
	public Local getBaseLocal(Stmt stmt) {
		if (stmt.containsInvokeExpr()) {
			InvokeExpr iexpr = stmt.getInvokeExpr();
			if (isField()) {
				if (iexpr instanceof InstanceInvokeExpr) {
					InstanceInvokeExpr iiexpr = (InstanceInvokeExpr) iexpr;
					return (Local) iiexpr.getBase();
				}
			} else if (isParameter()) {
				int idx = getParameterIndex();
				if (idx < iexpr.getArgCount()) {
					Value val = iexpr.getArg(idx);
					if (val instanceof Local)
						return (Local) val;
				}
			} else if (isReturn()) {
				if (stmt instanceof AssignStmt) {
					AssignStmt assignStmt = (AssignStmt) stmt;
					Value lop = assignStmt.getLeftOp();
					if (lop instanceof Local)
						return (Local) lop;
				}
			}
		}
		return null;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy