Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions soot-infoflow-android/schema/SourcesAndSinks.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,34 @@

<xs:element name="sinkSources">
<xs:complexType>
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="category" type="categoryType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:element name="defineStereotype" type="stereotypeType" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:complexType>
</xs:element>

<xs:complexType name="stereotypeTypeReference">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:any processContents="lax" />
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>

<xs:complexType name="stereotypeType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:any processContents="lax" />
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
<xs:attribute name="description" type="xs:string" use="optional" />
</xs:complexType>
<!-- Help for describing the method for sinkSources -->
<xs:complexType name="categoryType">
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="method" type="methodType" />
<xs:element name="field" type="fieldType" />
<xs:element name="stereotype" type="stereotypeTypeReference" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
Expand All @@ -27,6 +43,7 @@
<xs:element name="base" type="apElement" minOccurs="0" maxOccurs="1"/>
<xs:element name="return" type="apElement" minOccurs="0" maxOccurs="1" />
<xs:element name="param" type="apElementWithIndex" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="stereotype" type="stereotypeTypeReference" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:choice>
<xs:sequence>
Expand All @@ -41,6 +58,7 @@
<xs:complexType name="fieldType">
<xs:sequence>
<xs:element name="accessPath" type="metaPath" minOccurs="0" maxOccurs="1"/>
<xs:element name="stereotype" type="stereotypeTypeReference" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="signature" type="xs:string" use="required" />
<xs:attribute name="description" type="xs:string" use="optional" />
Expand All @@ -57,9 +75,11 @@
<xs:complexType name="apElement">
<xs:sequence>
<xs:element name="accessPath" type="metaPath" maxOccurs="unbounded"/>
<xs:element name="stereotype" type="stereotypeTypeReference" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional" />
<xs:attribute name="description" type="xs:string" use="optional" />
<xs:attribute name="triggerAdditionalFlow" type="xs:boolean" use="optional" />
</xs:complexType>

<xs:complexType name="apElementWithIndex">
Expand All @@ -81,6 +101,7 @@
<xs:complexType name="metaPath">
<xs:sequence>
<xs:element name="pathElement" type="pathElementType" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="stereotype" type="stereotypeTypeReference" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="isSource" type="xs:boolean" default="false"/>
<xs:attribute name="isSink" type="xs:boolean" default="false"/>
Expand All @@ -96,6 +117,30 @@
</xs:simpleContent>
</xs:complexType>

<xs:complexType name="valueParam">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="index" type="xs:int" use="required"/>
<xs:attribute name="regex" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="caseSensitive" type="xs:boolean" use="optional" default="false"/>
</xs:extension>
</xs:simpleContent>

</xs:complexType>

<xs:complexType name="valueOnPath">
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="param" type="valueParam" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="stereotype" type="stereotypeTypeReference" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="invocation" type="xs:string" use="required"/>
</xs:complexType>

<xs:complexType name="turnAround">
<xs:attribute name="invocation" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="additionalFlowConditionType">
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="unbounded">
Expand All @@ -109,6 +154,9 @@
<xs:attribute name="className" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="valueOnPath" type="valueOnPath" />
<xs:element name="turnAround" type="turnAround" />
<xs:element name="stereotype" type="stereotypeTypeReference" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="excludeClassName">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import soot.jimple.infoflow.android.data.AndroidMethod;
import soot.jimple.infoflow.android.data.CategoryDefinition;
import soot.jimple.infoflow.data.AbstractMethodAndClass;
import soot.jimple.infoflow.data.ValueOnPath;
import soot.jimple.infoflow.data.ValueOnPath.Parameter;
import soot.jimple.infoflow.river.conditions.SignatureFlowCondition;
import soot.jimple.infoflow.sourcesSinks.definitions.AccessPathTuple;
import soot.jimple.infoflow.sourcesSinks.definitions.FieldSourceSinkDefinition;
Expand Down Expand Up @@ -105,18 +107,23 @@ protected class SAXHandler extends DefaultHandler {

protected String accessPathParentElement = "";
protected String description = "";
protected boolean triggerAdditionalFlow;

protected Set<AccessPathTuple> baseAPs = new HashSet<>();
protected List<Set<AccessPathTuple>> paramAPs = new ArrayList<>();
protected Set<AccessPathTuple> returnAPs = new HashSet<>();

protected ICategoryFilter categoryFilter = null;

private Set<String> turnAroundPaths;
private Set<String> signaturesOnPath = new HashSet<>();
private Set<String> classNamesOnPath = new HashSet<>();
private Set<ValueOnPath> valuesOnPath = new HashSet<>();

private Set<String> excludedClassNames = new HashSet<>();
private Set<SourceSinkCondition> conditions = new HashSet<>();
private ValueOnPath vop;
private Parameter param;

public SAXHandler() {
}
Expand Down Expand Up @@ -158,11 +165,16 @@ public void startElement(String uri, String localName, String qName, Attributes
case XMLConstants.BASE_TAG:
accessPathParentElement = qNameLower;
description = attributes.getValue(XMLConstants.DESCRIPTION_ATTRIBUTE);
String t = attributes.getValue(XMLConstants.TRIGGERADDITIONALFLOW_ATTRIBUTE);
// true by default for the base tag
triggerAdditionalFlow = t == null || t.equalsIgnoreCase("true");
break;

case XMLConstants.RETURN_TAG:
accessPathParentElement = qNameLower;
description = attributes.getValue(XMLConstants.DESCRIPTION_ATTRIBUTE);
t = attributes.getValue(XMLConstants.TRIGGERADDITIONALFLOW_ATTRIBUTE);
triggerAdditionalFlow = t != null && t.equalsIgnoreCase("true");
break;

case XMLConstants.PARAM_TAG:
Expand All @@ -177,10 +189,18 @@ public void startElement(String uri, String localName, String qName, Attributes
handleStarttagSignatureOnPath(attributes);
break;

case XMLConstants.VALUE_ON_PATH_TAG:
handleStarttagValueOnPath(attributes);
break;

case XMLConstants.CLASS_NAME_ON_PATH_TAG:
handleStarttagClassNameOnPath(attributes);
break;

case XMLConstants.TURN_AROUND_TAG:
handleStarttagTurnAround(attributes);
break;

case XMLConstants.EXCLUDE_CLASS_NAME_TAG:
handleStarttagExcludeClassName(attributes);
break;
Expand Down Expand Up @@ -254,6 +274,22 @@ protected void handleStarttagAccesspath(Attributes attributes) {
}

protected void handleStarttagParam(Attributes attributes, String qNameLower) {
if (vop != null) {
String tempStr = attributes.getValue(XMLConstants.INDEX_ATTRIBUTE);
if (tempStr != null && !tempStr.isEmpty())
paramIndex = Integer.parseInt(tempStr);
tempStr = attributes.getValue(XMLConstants.REGEX_ATTRIBUTE);
boolean regex = false;
if (tempStr != null && !tempStr.isEmpty())
regex = Boolean.parseBoolean(tempStr);
tempStr = attributes.getValue(XMLConstants.CASE_SENSITIVE_ATTRIBUTE);
boolean casesensitive = false;
if (tempStr != null && !tempStr.isEmpty())
casesensitive = Boolean.parseBoolean(tempStr);
param = new ValueOnPath.Parameter(paramIndex, regex, casesensitive);
vop.add(param);
return;
}
if ((methodSignature != null || fieldSignature != null) && attributes != null) {
String tempStr = attributes.getValue(XMLConstants.INDEX_ATTRIBUTE);
if (tempStr != null && !tempStr.isEmpty())
Expand All @@ -265,6 +301,8 @@ protected void handleStarttagParam(Attributes attributes, String qNameLower) {
}
accessPathParentElement = qNameLower;
description = attributes.getValue(XMLConstants.DESCRIPTION_ATTRIBUTE);
String t = attributes.getValue(XMLConstants.TRIGGERADDITIONALFLOW_ATTRIBUTE);
triggerAdditionalFlow = t != null && t.equalsIgnoreCase("true");
}

protected void handleStarttagPathelement(Attributes attributes) {
Expand All @@ -290,6 +328,25 @@ protected void handleStarttagSignatureOnPath(Attributes attributes) {
}
}

protected void handleStarttagValueOnPath(Attributes attributes) {
String invocation = getStringAttribute(attributes, XMLConstants.INVOCATION_ATTRIBUTE);
if (invocation != null) {
if (valuesOnPath == null)
valuesOnPath = new HashSet<>();
vop = new ValueOnPath("<" + invocation + ">");
valuesOnPath.add(vop);
}
}

protected void handleStarttagTurnAround(Attributes attributes) {
String invocationName = getStringAttribute(attributes, XMLConstants.INVOCATION_ATTRIBUTE);
if (invocationName != null) {
if (turnAroundPaths == null)
turnAroundPaths = new HashSet<>();
turnAroundPaths.add(invocationName);
}
}

protected void handleStarttagClassNameOnPath(Attributes attributes) {
String className = getStringAttribute(attributes, XMLConstants.CLASS_NAME_ATTRIBUTE);
if (className != null) {
Expand Down Expand Up @@ -331,6 +388,10 @@ private String parseSignature(Attributes attributes) {
**/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (param != null) {
param.setContentToMatch(new String(ch, start, length));
param = null;
}
}

/**
Expand Down Expand Up @@ -391,15 +452,18 @@ public void endElement(String uri, String localName, String qName) throws SAXExc
accessPathParentElement = "";
paramIndex = -1;
paramTypes.clear();
vop = null;
param = null;
break;

case XMLConstants.ADDITIONAL_FLOW_CONDITION_TAG:
if (!classNamesOnPath.isEmpty() || !signaturesOnPath.isEmpty()) {
if (!classNamesOnPath.isEmpty() || !signaturesOnPath.isEmpty() || !valuesOnPath.isEmpty()) {
SignatureFlowCondition additionalFlowCondition = new SignatureFlowCondition(classNamesOnPath,
signaturesOnPath, excludedClassNames);
signaturesOnPath, valuesOnPath, excludedClassNames);
// Reset both for a new condition
classNamesOnPath = new HashSet<>();
signaturesOnPath = new HashSet<>();
valuesOnPath = new HashSet<>();

excludedClassNames = new HashSet<>();

Expand All @@ -422,7 +486,8 @@ protected void handleEndtagMethod() {
if (tempMeth != null) {
@SuppressWarnings("unchecked")
ISourceSinkDefinition ssd = createMethodSourceSinkDefinition(tempMeth, baseAPs,
paramAPs.toArray(new Set[paramAPs.size()]), returnAPs, callType, category, conditions);
paramAPs.toArray(new Set[paramAPs.size()]), returnAPs, callType, category, conditions,
turnAroundPaths);
addSourceSinkDefinition(methodSignature, ssd);
} else {
logger.error("Invalid method signature: " + methodSignature);
Expand All @@ -431,6 +496,7 @@ protected void handleEndtagMethod() {
}

// Start a new method and discard our old data
turnAroundPaths = null;
methodSignature = null;
fieldSignature = null;
baseAPs = new HashSet<>();
Expand Down Expand Up @@ -489,6 +555,8 @@ protected void handleEndtagAccesspath() {
if (description != null && !description.isEmpty())
apt.setDescription(description);

apt.setTriggerAdditionalFlow(triggerAdditionalFlow);

// Simplify the AP after setting the description for not breaking the generic
// source definition
apt = apt.simplify();
Expand All @@ -515,6 +583,7 @@ protected void handleEndtagAccesspath() {
isSink = false;
pathElements = null;
pathElementTypes = null;
triggerAdditionalFlow = false;

description = null;
}
Expand Down Expand Up @@ -666,23 +735,25 @@ protected abstract ISourceSinkDefinition createMethodSourceSinkDefinition(Abstra
/**
* Factory method for {@link MethodSourceSinkDefinition} instances
*
* @param method The method that is to be defined as a source or sink
* @param baseAPs The access paths rooted in the base object that shall be
* considered as sources or sinks
* @param paramAPs The access paths rooted in parameters that shall be
* considered as sources or sinks. The index in the set
* corresponds to the index of the formal parameter to which
* the respective set of access paths belongs.
* @param returnAPs The access paths rooted in the return object that shall be
* considered as sources or sinks
* @param callType The type of call (normal call, callback, etc.)
* @param conditions Conditions which has to be true for the definition to be
* valid
* @param method The method that is to be defined as a source or sink
* @param baseAPs The access paths rooted in the base object that shall
* be considered as sources or sinks
* @param paramAPs The access paths rooted in parameters that shall be
* considered as sources or sinks. The index in the set
* corresponds to the index of the formal parameter to
* which the respective set of access paths belongs.
* @param returnAPs The access paths rooted in the return object that
* shall be considered as sources or sinks
* @param callType The type of call (normal call, callback, etc.)
* @param conditions Conditions which has to be true for the definition to
* be valid
* @param turnAroundPaths a set of turn around path method invocations
* @return The newly created {@link MethodSourceSinkDefinition} instance
*/
protected abstract ISourceSinkDefinition createMethodSourceSinkDefinition(AbstractMethodAndClass method,
Set<AccessPathTuple> baseAPs, Set<AccessPathTuple>[] paramAPs, Set<AccessPathTuple> returnAPs,
CallType callType, ISourceSinkCategory category, Set<SourceSinkCondition> conditions);
CallType callType, ISourceSinkCategory category, Set<SourceSinkCondition> conditions,
Set<String> turnAroundPaths);

/**
* Reads the method or field signature from the given attribute map
Expand Down
Loading