/*
* Copyright (C) 2015 The Pennsylvania State University and the University of Wisconsin
* Systems and Internet Infrastructure Security Laboratory
*
* Author: Damien Octeau
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.psu.cse.siis.ic3;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.Scene;
import soot.SootMethod;
import soot.Type;
import soot.Unit;
import soot.jimple.InvokeExpr;
import soot.jimple.Stmt;
import com.google.protobuf.TextFormat;
import edu.psu.cse.siis.coal.AnalysisParameters;
import edu.psu.cse.siis.coal.Constants;
import edu.psu.cse.siis.coal.Model;
import edu.psu.cse.siis.coal.PropagationTimers;
import edu.psu.cse.siis.coal.Result;
import edu.psu.cse.siis.coal.Results;
import edu.psu.cse.siis.coal.arguments.Argument;
import edu.psu.cse.siis.coal.field.values.FieldValue;
import edu.psu.cse.siis.coal.field.values.ScalarFieldValue;
import edu.psu.cse.siis.coal.field.values.TopFieldValue;
import edu.psu.cse.siis.coal.values.BasePropagationValue;
import edu.psu.cse.siis.coal.values.BottomPropagationValue;
import edu.psu.cse.siis.coal.values.PathValue;
import edu.psu.cse.siis.coal.values.PropagationValue;
import edu.psu.cse.siis.coal.values.TopPropagationValue;
import edu.psu.cse.siis.ic3.Ic3Data.Application.Component;
import edu.psu.cse.siis.ic3.Ic3Data.Application.Component.ComponentKind;
import edu.psu.cse.siis.ic3.Ic3Data.Application.Component.ExitPoint;
import edu.psu.cse.siis.ic3.Ic3Data.Application.Component.ExitPoint.Intent;
import edu.psu.cse.siis.ic3.Ic3Data.Application.Component.ExitPoint.Uri;
import edu.psu.cse.siis.ic3.Ic3Data.Application.Component.Extra;
import edu.psu.cse.siis.ic3.Ic3Data.Application.Component.Instruction;
import edu.psu.cse.siis.ic3.Ic3Data.Attribute;
import edu.psu.cse.siis.ic3.Ic3Data.AttributeKind;
import edu.psu.cse.siis.ic3.manifest.ManifestComponent;
import edu.psu.cse.siis.ic3.manifest.ManifestData;
import edu.psu.cse.siis.ic3.manifest.ManifestIntentFilter;
import edu.psu.cse.siis.ic3.manifest.ManifestPullParser;
public class ProtobufResultProcessor {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final String ENTRY_POINT_INTENT = "<INTENT>";
private final int[] preciseNonLinking = { 0, 0, 0, 0 };
private final int[] preciseLinking = { 0, 0, 0, 0 };
private final int[] imprecise = { 0, 0, 0, 0, 0 };
private final int[] top = { 0, 0, 0 };
private final int[] bottom = { 0, 0, 0 };
private final int[] nonexistent = { 0, 0, 0 };
private final int[] preciseFieldValueCount = { 0, 0, 0 };
private final int[] partiallyPreciseFieldValueCount = { 0, 0, 0 };
private final int[] impreciseFieldValueCount = { 0, 0, 0 };
private int intentWithData = 0;
private int providerArgument = 0;
public void processResult(String appName, Ic3Data.Application.Builder ic3Builder,
String protobufDestination, boolean binary,
Map<String, Ic3Data.Application.Component.Builder> componentNameToBuilderMap,
int analysisClassesCount, Writer writer) throws IOException {
for (Result result : Results.getResults()) {
((Ic3Result) result).dump();
analyzeResult(result);
writeResultToProtobuf(result, ic3Builder, componentNameToBuilderMap);
}
ic3Builder.setAnalysisEnd(System.currentTimeMillis() / 1000);
String extension = binary ? "dat" : "txt";
String path =
String.format("%s/%s_%s.%s", protobufDestination, ic3Builder.getName(),
ic3Builder.getVersion(), extension);
System.out.println("PATH: " + path);
if (binary) {
FileOutputStream fileOutputStream = new FileOutputStream(path);
ic3Builder.build().writeTo(fileOutputStream);
fileOutputStream.close();
} else {
FileWriter fileWriter = new FileWriter(path);
TextFormat.print(ic3Builder, fileWriter);
fileWriter.close();
}
Timers.v().totalTimer.end();
String statistics =
appName + " " + analysisClassesCount + " " + PropagationTimers.v().reachableMethods + " "
+ preciseNonLinking[0] + " " + preciseNonLinking[3] + " " + preciseNonLinking[1] + " "
+ preciseNonLinking[2] + " " + preciseLinking[0] + " " + preciseLinking[3] + " "
+ preciseLinking[1] + " " + preciseLinking[2] + " " + imprecise[0] + " " + imprecise[3]
+ " " + imprecise[1] + " " + imprecise[2] + " " + bottom[0] + " " + bottom[1] + " "
+ bottom[2] + " " + top[0] + " " + top[1] + " " + top[2] + " " + nonexistent[0] + " "
+ nonexistent[1] + " " + nonexistent[2] + " " + providerArgument + " " + imprecise[4]
+ " " + preciseFieldValueCount[0] + " " + preciseFieldValueCount[1] + " "
+ preciseFieldValueCount[2] + " " + partiallyPreciseFieldValueCount[0] + " "
+ partiallyPreciseFieldValueCount[1] + " " + partiallyPreciseFieldValueCount[2] + " "
+ impreciseFieldValueCount[0] + " " + impreciseFieldValueCount[1] + " "
+ impreciseFieldValueCount[2] + " " + PropagationTimers.v().modelParsing.getTime()
+ " " + Timers.v().mainGeneration.getTime() + " "
+ Timers.v().entryPointMapping.getTime() + " " + Timers.v().classLoading.getTime()
+ " " + PropagationTimers.v().problemGeneration.getTime() + " "
+ PropagationTimers.v().ideSolution.getTime() + " "
+ PropagationTimers.v().valueComposition.getTime() + " "
+ PropagationTimers.v().resultGeneration.getTime() + " "
+ (PropagationTimers.v().soot.getTime() - PropagationTimers.v().totalTimer.getTime())
+ " " + (Timers.v().misc.getTime() + PropagationTimers.v().misc.getTime()) + " "
+ Timers.v().totalTimer.getTime() + "\n";
if (logger.isInfoEnabled()) {
logger.info(statistics);
}
if (writer != null) {
writer.write(statistics);
writer.close();
}
}
@SuppressWarnings("unchecked")
private void writeResultToProtobuf(Result result, Ic3Data.Application.Builder ic3Builder,
Map<String, Component.Builder> componentNameToBuilderMap) {
Map<String, Set<Extra>> componentToExtrasMap = new HashMap<>();
Map<String, ManifestComponent> dynamicReceivers = new HashMap<>();
Map<SootMethod, Set<String>> entryPointMap = ((Ic3Result) result).getEntryPointMap();
for (Map.Entry<Unit, Map<Integer, Object>> entry : result.getResults().entrySet()) {
Unit unit = entry.getKey();
Argument[] arguments = Model.v().getArgumentsForQuery((Stmt) unit);
if (arguments != null) {
SootMethod method = AnalysisParameters.v().getIcfg().getMethodOf(unit);
Instruction.Builder instructionBuilder = unitToInstructionBuilder(method, unit);
Map<String, Object> valueMap = new HashMap<>(arguments.length);
Map<Integer, Object> argnumToValueMap = entry.getValue();
for (Argument argument : arguments) {
valueMap.put(argument.getProperty("valueType"),
argnumToValueMap.get(argument.getArgnum()[0]));
}
if (valueMap.containsKey("activity")) {
insertProtobufExitPoint(instructionBuilder,
(BasePropagationValue) valueMap.get("activity"), ComponentKind.ACTIVITY, null, null,
entryPointMap.get(method), componentNameToBuilderMap);
} else if (valueMap.containsKey("service")) {
insertProtobufExitPoint(instructionBuilder,
(BasePropagationValue) valueMap.get("service"), ComponentKind.SERVICE, null, null,
entryPointMap.get(method), componentNameToBuilderMap);
} else if (valueMap.containsKey("receiver")) {
insertProtobufExitPoint(instructionBuilder,
(BasePropagationValue) valueMap.get("receiver"), ComponentKind.RECEIVER,
(Set<String>) valueMap.get("permission"), null, entryPointMap.get(method),
componentNameToBuilderMap);
} else if (valueMap.containsKey("intentFilter")) {
insertDynamicReceiver(dynamicReceivers, (Set<String>) valueMap.get("permission"),
(Set<String>) valueMap.get("receiverType"),
(BasePropagationValue) valueMap.get("intentFilter"), method, unit);
} else if (valueMap.containsKey("provider")) {
insertProtobufExitPoint(instructionBuilder,
(BasePropagationValue) valueMap.get("provider"), ComponentKind.PROVIDER, null, null,
entryPointMap.get(method), componentNameToBuilderMap);
} else if (valueMap.containsKey("authority")) {
insertProtobufExitPoint(instructionBuilder,
getUriValueForAuthorities((Set<String>) valueMap.get("authority")),
ComponentKind.PROVIDER, null, null, entryPointMap.get(method),
componentNameToBuilderMap);
} else if (valueMap.containsKey("pendingIntent")) {
BasePropagationValue baseCollectingValue =
(BasePropagationValue) valueMap.get("pendingIntent");
String targetType =
baseCollectingValue instanceof PropagationValue ? (String) ((PropagationValue) baseCollectingValue)
.getValuesForField("targetType").iterator().next().getValue()
: null;
Set<String> permissions = (Set<String>) valueMap.get("permission");
if (targetType != null) {
insertProtobufExitPoint(instructionBuilder, baseCollectingValue,
stringToComponentKind(targetType), permissions, null, entryPointMap.get(method),
componentNameToBuilderMap);
} else {
for (ComponentKind target : Arrays.asList(ComponentKind.ACTIVITY,
ComponentKind.RECEIVER, ComponentKind.SERVICE)) {
insertProtobufExitPoint(instructionBuilder, baseCollectingValue, target, null, null,
entryPointMap.get(method), componentNameToBuilderMap);
}
}
} else if (valueMap.containsKey("componentExtra")) {
Set<String> extras = (Set<String>) valueMap.get("componentExtra");
if (extras != null) {
for (String component : entryPointMap.get(method)) {
Set<Extra> existingExtras = componentToExtrasMap.get(component);
if (existingExtras == null) {
existingExtras = new HashSet<>();
componentToExtrasMap.put(component, existingExtras);
}
for (String extra : extras) {
Extra.Builder extraBuilder = Extra.newBuilder();
extraBuilder.setExtra(extra);
extraBuilder.setInstruction(instructionBuilder);
existingExtras.add(extraBuilder.build());
}
}
}
}
}
}
for (Map.Entry<String, Set<Extra>> entry : componentToExtrasMap.entrySet()) {
componentNameToBuilderMap.get(entry.getKey()).addAllExtras(entry.getValue());
}
for (Component.Builder componentBuilder : componentNameToBuilderMap.values()) {
ic3Builder.addComponents(componentBuilder);
}
for (ManifestComponent manifestComponent : dynamicReceivers.values()) {
Component.Builder componentBuilder =
ManifestPullParser.makeProtobufComponentBuilder(manifestComponent,
ComponentKind.DYNAMIC_RECEIVER);
componentBuilder.setRegistrationInstruction(unitToInstructionBuilder(
manifestComponent.getRegistrationMethod(), manifestComponent.getRegistrationUnit()));
ic3Builder.addComponents(componentBuilder);
}
}
private Instruction.Builder unitToInstructionBuilder(SootMethod method, Unit unit) {
Instruction.Builder builder = Instruction.newBuilder();
builder.setClassName(method.getDeclaringClass().getName());
builder.setMethod(method.getSignature());
builder.setStatement(unit.toString());
builder.setId(getIdForUnit(unit, method));
return builder;
}
private void insertProtobufExitPoint(Instruction.Builder instructionBuilder,
BasePropagationValue intentValue, ComponentKind componentKind, Set<String> intentPermissions,
Integer missingIntents, Set<String> exitPointComponents,
Map<String, Component.Builder> componentNameToBuilderMap) {
for (String exitPointComponent : exitPointComponents) {
ExitPoint.Builder exitPointBuilder = ExitPoint.newBuilder();
exitPointBuilder.setInstruction(instructionBuilder).setKind(componentKind);
PropagationValue collectingValue = null;
if (intentValue == null || intentValue instanceof TopPropagationValue
|| intentValue instanceof BottomPropagationValue) {
missingIntents = 0;
} else if (intentValue instanceof PropagationValue) {
collectingValue = (PropagationValue) intentValue;
if (collectingValue.getPathValues() == null || collectingValue.getPathValues().size() == 0) {
missingIntents = 0;
}
} else {
throw new RuntimeException("Unknown CollectingValue type: " + intentValue.getClass());
}
if (missingIntents != null) {
exitPointBuilder.setMissing(missingIntents);
} else {
Set<PathValue> pathValues = collectingValue.getPathValues();
if (pathValues != null) {
for (PathValue pathValue : pathValues) {
if (componentKind.equals(ComponentKind.PROVIDER)) {
exitPointBuilder.addUris(makeProtobufUriBuilder(pathValue));
} else {
if (intentPermissions != null && intentPermissions.size() != 0) {
for (String intentPermission : intentPermissions) {
exitPointBuilder.addIntents(makeProtobufIntentBuilder(pathValue).setPermission(
intentPermission));
}
} else {
exitPointBuilder.addIntents(makeProtobufIntentBuilder(pathValue));
}
}
}
}
}
Component.Builder componentBuilder = componentNameToBuilderMap.get(exitPointComponent);
componentBuilder.addExitPoints(exitPointBuilder);
}
}
private Intent.Builder makeProtobufIntentBuilder(PathValue intentValue) {
Intent.Builder intentBuilder = Intent.newBuilder();
insertSingleValuedIntentAttribute(intentValue, "action", AttributeKind.ACTION, intentBuilder);
Set<String> categories = intentValue.getSetStringFieldValue("categories");
if (categories != null) {
if (categories.contains(null)) {
categories.remove(null);
categories.add(Constants.NULL_STRING);
}
intentBuilder.addAttributes(Attribute.newBuilder().setKind(AttributeKind.CATEGORY)
.addAllValue(categories));
}
Set<Integer> flags = intentValue.getSetFieldValue("flags", Integer.class);
if (flags != null) {
intentBuilder.addAttributes(Attribute.newBuilder().setKind(AttributeKind.FLAG)
.addAllIntValue(flags));
}
// String mimeType = intentValue.getSingleStringFieldValue("dataType");
// if (mimeType != null) {
// String[] typeParts = mimeType.split("/");
// String type;
// String subtype;
// if (typeParts.length == 2) {
// type = typeParts[0];
// subtype = typeParts[1];
// } else {
// type = Constants.ANY_STRING;
// subtype = Constants.ANY_STRING;
// }
// intentBuilder
// .addAttributes(Attribute.newBuilder().setKind(AttributeKind.TYPE).addValue(type));
// intentBuilder.addAttributes(Attribute.newBuilder().setKind(AttributeKind.SUBTYPE)
// .addValue(subtype));
// }
insertSingleValuedIntentAttribute(intentValue, "dataType", AttributeKind.TYPE, intentBuilder);
Set<String> extras = intentValue.getSetStringFieldValue("extras");
if (extras != null) {
if (extras.contains(null)) {
extras.remove(null);
extras.add(Constants.NULL_STRING);
}
intentBuilder.addAttributes(Attribute.newBuilder().setKind(AttributeKind.EXTRA)
.addAllValue(extras));
}
insertSingleValuedIntentAttribute(intentValue, "clazz", AttributeKind.CLASS, intentBuilder);
insertSingleValuedIntentAttribute(intentValue, "package", AttributeKind.PACKAGE, intentBuilder);
insertSingleValuedIntentAttribute(intentValue, "scheme", AttributeKind.SCHEME, intentBuilder);
insertSingleValuedIntentAttribute(intentValue, "ssp", AttributeKind.SSP, intentBuilder);
insertSingleValuedIntentAttribute(intentValue, "uri", AttributeKind.URI, intentBuilder);
insertSingleValuedIntentAttribute(intentValue, "path", AttributeKind.PATH, intentBuilder);
insertSingleValuedIntentAttribute(intentValue, "query", AttributeKind.QUERY, intentBuilder);
insertSingleValuedIntentAttribute(intentValue, "authority", AttributeKind.AUTHORITY,
intentBuilder);
return intentBuilder;
}
private void insertSingleValuedIntentAttribute(PathValue pathValue, String attribute,
AttributeKind kind, Intent.Builder intentBuilder) {
String attributeValue = pathValue.getScalarStringFieldValue(attribute);
if (attributeValue != null) {
intentBuilder.addAttributes(Attribute.newBuilder().setKind(kind).addValue(attributeValue));
}
}
private Uri.Builder makeProtobufUriBuilder(PathValue uriValue) {
Uri.Builder uriBuilder = Uri.newBuilder();
insertSingleValuedUriAttribute(uriValue, "scheme", AttributeKind.SCHEME, uriBuilder);
insertSingleValuedUriAttribute(uriValue, "ssp", AttributeKind.SSP, uriBuilder);
insertSingleValuedUriAttribute(uriValue, "uri", AttributeKind.URI, uriBuilder);
insertSingleValuedUriAttribute(uriValue, "path", AttributeKind.PATH, uriBuilder);
insertSingleValuedUriAttribute(uriValue, "query", AttributeKind.QUERY, uriBuilder);
insertSingleValuedUriAttribute(uriValue, "authority", AttributeKind.AUTHORITY, uriBuilder);
return uriBuilder;
}
private void insertSingleValuedUriAttribute(PathValue pathValue, String attribute,
AttributeKind kind, Uri.Builder uriBuilder) {
String attributeValue = pathValue.getScalarStringFieldValue(attribute);
if (attributeValue != null) {
uriBuilder.addAttributes(Attribute.newBuilder().setKind(kind).addValue(attributeValue));
}
}
private ComponentKind stringToComponentKind(String componentKind) {
switch (componentKind) {
case "a":
return ComponentKind.ACTIVITY;
case "s":
return ComponentKind.SERVICE;
case "r":
return ComponentKind.RECEIVER;
default:
throw new RuntimeException("Unknown component kind: " + componentKind);
}
}
private void insertDynamicReceiver(Map<String, ManifestComponent> dynamicReceivers,
Set<String> permissions, Set<String> receiverTypes, BasePropagationValue intentFilters,
SootMethod method, Unit unit) {
if (permissions == null) {
permissions = Collections.singleton(null);
}
for (String receiverType : receiverTypes) {
for (String permission : permissions) {
insertDynamicReceiverHelper(dynamicReceivers, permission, receiverType, intentFilters,
method, unit);
}
}
}
private void insertDynamicReceiverHelper(Map<String, ManifestComponent> dynamicReceivers,
String permission, String receiverType, BasePropagationValue intentFilters,
SootMethod method, Unit unit) {
Integer missingIntentFilters;
Set<ManifestIntentFilter> manifestIntentFilters;
if (intentFilters == null || intentFilters instanceof TopPropagationValue
|| intentFilters instanceof BottomPropagationValue) {
missingIntentFilters = 0;
manifestIntentFilters = null;
} else if (intentFilters instanceof PropagationValue) {
missingIntentFilters = null;
PropagationValue collectingValue = (PropagationValue) intentFilters;
manifestIntentFilters = new HashSet<>();
for (PathValue branchValue : collectingValue.getPathValues()) {
Integer filterPriority = null;
FieldValue priorityFieldValue = branchValue.getFieldValue("priority");
if (priorityFieldValue != null) {
filterPriority = (Integer) priorityFieldValue.getValue();
}
manifestIntentFilters.add(new ManifestIntentFilter(branchValue
.getSetStringFieldValue("actions"), branchValue.getSetStringFieldValue("categories"),
false, makeManifestData(branchValue), filterPriority));
}
} else {
throw new RuntimeException("Unknown intent filter type: " + intentFilters.getClass());
}
ManifestComponent manifestComponent = dynamicReceivers.get(receiverType);
if (manifestComponent == null) {
manifestComponent =
new ManifestComponent(
edu.psu.cse.siis.ic3.db.Constants.ComponentShortType.DYNAMIC_RECEIVER, receiverType,
true, true, permission, null, missingIntentFilters, method, unit);
dynamicReceivers.put(receiverType, manifestComponent);
}
manifestComponent.addIntentFilters(manifestIntentFilters);
}
private List<ManifestData> makeManifestData(PathValue branchValue) {
Set<String> mimeTypes = branchValue.getSetStringFieldValue("dataType");
Set<DataAuthority> authorities =
branchValue.getSetFieldValue("authorities", DataAuthority.class);
Set<String> paths = branchValue.getSetStringFieldValue("paths");
Set<String> schemes = branchValue.getSetStringFieldValue("schemes");
if (mimeTypes == null && authorities == null && paths == null && schemes == null) {
return null;
}
if (mimeTypes == null) {
mimeTypes = Collections.singleton(null);
}
if (authorities == null) {
authorities = Collections.singleton(new DataAuthority(null, null));
}
if (paths == null) {
paths = Collections.singleton(null);
}
if (schemes == null) {
schemes = Collections.singleton(null);
}
List<ManifestData> result = new ArrayList<>();
for (String mimeType : mimeTypes) {
for (DataAuthority dataAuthority : authorities) {
for (String dataPath : paths) {
for (String scheme : schemes) {
result.add(new ManifestData(scheme, dataAuthority.getHost(), dataAuthority.getPort(),
dataPath, mimeType));
}
}
}
}
return result;
}
private BasePropagationValue getUriValueForAuthorities(Set<String> authorities) {
if (authorities == null) {
return null;
}
PropagationValue collectingValue = new PropagationValue();
for (String authority : authorities) {
PathValue branchValue = new PathValue();
ScalarFieldValue schemeFieldValue = new ScalarFieldValue("content");
branchValue.addFieldEntry("scheme", schemeFieldValue);
ScalarFieldValue authorityFieldValue = new ScalarFieldValue(authority);
branchValue.addFieldEntry("authority", authorityFieldValue);
collectingValue.addPathValue(branchValue);
}
return collectingValue;
}
private int getIdForUnit(Unit unit, SootMethod method) {
int id = 0;
for (Unit currentUnit : method.getActiveBody().getUnits()) {
if (currentUnit == unit) {
return id;
}
++id;
}
return -1;
}
@SuppressWarnings("unchecked")
private void analyzeResult(Result result) {
Set<String> nonLinkingFieldNames = new HashSet<>();
nonLinkingFieldNames.add("extras");
nonLinkingFieldNames.add("flags");
nonLinkingFieldNames.add("fragment");
nonLinkingFieldNames.add("query");
for (Map.Entry<Unit, Map<Integer, Object>> entry0 : result.getResults().entrySet()) {
Collection<Object> argumentValues = entry0.getValue().values();
boolean top = false;
boolean bottom = false;
// This is true only if the linking field are precisely known.
boolean preciseLinking = true;
// This is true only if all fields are precisely known.
boolean preciseNonLinking = true;
boolean nonexistent = false;
boolean intentWithUri = false;
boolean entryPointIntent = false;
int resultIndex = getResultIndex((Stmt) entry0.getKey());
for (Object value2 : argumentValues) {
if (value2 == null) {
nonexistent = true;
} else if (value2 instanceof TopPropagationValue) {
top = true;
} else if (value2 instanceof BottomPropagationValue) {
bottom = true;
} else if (value2 instanceof PropagationValue) {
PropagationValue collectingValue = (PropagationValue) value2;
for (PathValue branchValue : collectingValue.getPathValues()) {
intentWithUri = intentWithUri || isIntentWithUri(branchValue.getFieldMap());
for (Map.Entry<String, FieldValue> entry : branchValue.getFieldMap().entrySet()) {
String fieldName = entry.getKey();
FieldValue fieldValue = entry.getValue();
if (fieldValue instanceof TopFieldValue) {
if (nonLinkingFieldNames.contains(fieldName)) {
preciseNonLinking = false;
} else {
preciseNonLinking = false;
preciseLinking = false;
}
} else {
Object value = fieldValue.getValue();
if (value == null) {
continue;
}
if (value instanceof Set) {
Set<Object> values = (Set<Object>) value;
if (values.contains(Constants.ANY_STRING) || values.contains(Constants.ANY_CLASS)
|| values.contains(Constants.ANY_INT) || values.contains(ENTRY_POINT_INTENT)
|| values.contains("top")) {
if (values.contains(ENTRY_POINT_INTENT)) {
entryPointIntent = true;
}
preciseNonLinking = false;
if (!nonLinkingFieldNames.contains(fieldName)) {
preciseLinking = false;
}
}
} else {
if (value.equals(Constants.ANY_STRING) || value.equals(Constants.ANY_CLASS)
|| value.equals(Constants.ANY_INT) || value.equals(ENTRY_POINT_INTENT)
|| value.equals("top")) {
if (value.equals(ENTRY_POINT_INTENT)) {
entryPointIntent = true;
}
preciseNonLinking = false;
if (!nonLinkingFieldNames.contains(fieldName)) {
preciseLinking = false;
}
}
}
}
}
}
}
}
if (intentWithUri) {
++this.intentWithData;
}
if (nonexistent) {
if (Scene
.v()
.getActiveHierarchy()
.isClassSubclassOfIncluding(
AnalysisParameters.v().getIcfg().getMethodOf(entry0.getKey()).getDeclaringClass(),
Scene.v().getSootClass("android.content.ContentProvider"))) {
++this.providerArgument;
} else {
++this.nonexistent[resultIndex];
}
} else if (top) {
++this.top[resultIndex];
} else if (bottom) {
++this.bottom[resultIndex];
} else if (preciseNonLinking) {
if (intentWithUri) {
++this.preciseNonLinking[3];
} else {
++this.preciseNonLinking[resultIndex];
}
} else if (preciseLinking) {
if (intentWithUri) {
++this.preciseLinking[3];
} else {
++this.preciseLinking[resultIndex];
}
} else {
if (entryPointIntent) {
++this.imprecise[4];
} else if (intentWithUri) {
++this.imprecise[3];
} else {
++this.imprecise[resultIndex];
}
}
}
}
private boolean isIntentWithUri(Map<String, FieldValue> fieldMap) {
Set<String> fields = fieldMap.keySet();
if (fields.contains("action") || fields.contains("categories")) {
if ((fields.contains("uri") && fieldMap.get("uri") != null && fieldMap.get("uri").getValue() != null)
|| (fields.contains("path") && fieldMap.get("path") != null && fieldMap.get("path")
.getValue() != null)
|| (fields.contains("scheme") && fieldMap.get("scheme") != null && fieldMap.get("scheme")
.getValue() != null)
|| (fields.contains("ssp") && fieldMap.get("ssp") != null && fieldMap.get("ssp")
.getValue() != null)) {
return true;
}
}
return false;
}
private int getResultIndex(Stmt stmt) {
InvokeExpr invokeExpr = stmt.getInvokeExpr();
List<Type> types = invokeExpr.getMethod().getParameterTypes();
for (Type type : types) {
if (type.toString().equals("android.content.IntentFilter")) {
return 1;
} else if (type.toString().equals("android.net.Uri")) {
return 2;
}
}
return 0;
}
private boolean containsPartialDefinition(Set<Object> values) {
for (Object value : values) {
if (value instanceof String && ((String) value).contains("(.*)")) {
return true;
}
}
return false;
}
}