/* * 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; } }