@Override public void computeAliasTaints(Abstraction d1, Stmt src, Value targetValue, Set<Abstraction> taintSet, SootMethod method, Abstraction newAbs) { computeAliasTaintsInternal(d1, method, newAbs, Collections.<SootField>emptyList(), Collections.<Type>emptyList(), newAbs.getAccessPath().getTaintSubFields(), src); }
/** * Merges the two given access paths , i.e., adds the fields of ap2 to ap1. * * @param ap1 The access path to which to append the fields * @param ap2 The access path whose fields to append to ap1 * @return The new access path */ public AccessPath merge(AccessPath ap1, AccessPath ap2) { return appendFields(ap1, ap2.getFields(), ap2.getFieldTypes(), ap2.getTaintSubFields()); }
/** * Writes the given access path into the given XML stream writer * * @param accessPath The access path to write out * @param writer The stream writer into which to write the data * @throws XMLStreamException Thrown if the XML data cannot be written */ protected void writeAccessPath(AccessPath accessPath, XMLStreamWriter writer) throws XMLStreamException { writer.writeStartElement(XmlConstants.Tags.accessPath); if (accessPath.getPlainValue() != null) writer.writeAttribute(XmlConstants.Attributes.value, accessPath.getPlainValue().toString()); if (accessPath.getBaseType() != null) writer.writeAttribute(XmlConstants.Attributes.type, accessPath.getBaseType().toString()); writer.writeAttribute(XmlConstants.Attributes.taintSubFields, accessPath.getTaintSubFields() ? XmlConstants.Values.TRUE : XmlConstants.Values.FALSE); // Write out the fields if (accessPath.getFieldCount() > 0) { writer.writeStartElement(XmlConstants.Tags.fields); for (int i = 0; i < accessPath.getFieldCount(); i++) { writer.writeStartElement(XmlConstants.Tags.field); writer.writeAttribute(XmlConstants.Attributes.value, accessPath.getFields()[i].toString()); writer.writeAttribute(XmlConstants.Attributes.type, accessPath.getFieldTypes()[i].toString()); writer.writeEndElement(); } writer.writeEndElement(); } writer.writeEndElement(); }
@Override public Set<AccessPath> getTaintsForMethodInternal(Stmt stmt, AccessPath taintedPath) { assert stmt.containsInvokeExpr(); // Do not provide models for application classes if (!stmt.getInvokeExpr().getMethod().getDeclaringClass().isLibraryClass()) return null; // For the moment, we don't implement static taints on wrappers. Pass it on // not to break anything if (taintedPath.isStaticFieldRef()) return Collections.singleton(taintedPath); if (stmt.getInvokeExpr() instanceof InstanceInvokeExpr) { InstanceInvokeExpr iiExpr = (InstanceInvokeExpr) stmt.getInvokeExpr(); // If the base object is tainted, the return value is always tainted if (taintedPath.getPlainValue().equals(iiExpr.getBase())) if (stmt instanceof AssignStmt) return Collections.singleton(manager.getAccessPathFactory() .createAccessPath(((AssignStmt) stmt).getLeftOp(), taintedPath.getTaintSubFields())); } // If one of the parameters is tainted, the return value is tainted, too for (Value param : stmt.getInvokeExpr().getArgs()) if (taintedPath.getPlainValue().equals(param)) if (stmt instanceof AssignStmt) return Collections.singleton(manager.getAccessPathFactory() .createAccessPath(((AssignStmt) stmt).getLeftOp(), taintedPath.getTaintSubFields())); return Collections.emptySet(); }
/** * Checks whether the given access path matches the given definition * * @param sourceAccessPath * The access path to check * @param apt * The definition against which to check the access path * @return True if the given access path matches the given definition, otherwise * false */ private boolean accessPathMatches(AccessPath sourceAccessPath, AccessPathTuple apt) { // If the source or sink definitions does not specify any fields, it // always matches if (apt.getFields() == null || apt.getFields().length == 0 || sourceAccessPath == null) return true; for (int i = 0; i < apt.getFields().length; i++) { // If a.b.c.* is our defined sink and a.b is tainted, this is not a // leak. If a.b.* is tainted, it is. if (i >= sourceAccessPath.getFieldCount()) return sourceAccessPath.getTaintSubFields(); // Compare the fields if (!sourceAccessPath.getFields()[i].getName().equals(apt.getFields()[i])) return false; } return true; }
/** * value val gets new base, fields are preserved. * * @param original The original access path * @param val The new base value * @param reduceBases True if circular types shall be reduced to bases * @param arrayTaintType The way a tainted array shall be handled * @return This access path with the base replaced by the value given in the val * parameter */ public AccessPath copyWithNewValue(AccessPath original, Value val, Type newType, boolean cutFirstField, boolean reduceBases, ArrayTaintType arrayTaintType) { // If this copy would not add any new information, we can safely use the // old // object if (original.getPlainValue() != null && original.getPlainValue().equals(val) && original.getBaseType().equals(newType) && original.getArrayTaintType() == arrayTaintType) return original; // Create the new access path AccessPath newAP = createAccessPath(val, original.getFields(), newType, original.getFieldTypes(), original.getTaintSubFields(), cutFirstField, reduceBases, arrayTaintType, original.getCanHaveImmutableAliases()); // Again, check whether we can do without the new object if (newAP != null && newAP.equals(original)) return original; else return newAP; }
/** * Creates a custom. The semantics must be defined by the code that uses the * sink * * @param paraIdx The index of the parameter * @param accessPath The access path modeling the field inside the parameter * value * @param gap The gap in whose parameter the flow ends * @param userData Additional user data to be associated with the sink * @return The sink object */ public FlowSink createCustomSink(int paraIdx, AccessPath accessPath, GapDefinition gap, Object userData) { if (accessPath.isLocal()) { if (gap == null && !accessPath.getTaintSubFields() && !(accessPath.getBaseType() instanceof ArrayType)) throw new RuntimeException("Parameter locals cannot directly be sinks"); else return new FlowSink(SourceSinkType.Custom, paraIdx, accessPath.getBaseType().toString(), accessPath.getTaintSubFields(), gap, userData); } else if (accessPath.getFieldCount() < summaryAPLength) return new FlowSink(SourceSinkType.Custom, paraIdx, accessPath.getBaseType().toString(), sootFieldsToString(accessPath.getFields()), sootTypesToString(accessPath.getFieldTypes()), accessPath.getTaintSubFields(), gap, userData, false); else return new FlowSink(SourceSinkType.Custom, paraIdx, accessPath.getBaseType().toString(), sootFieldsToString(cutAPLength(accessPath.getFields())), sootTypesToString(cutAPLength(accessPath.getFieldTypes())), true, gap, userData, false); }
/** * Creates a sink that models a value assigned to a field reachable through a * parameter value * * @param paraIdx The index of the parameter * @param accessPath The access path modeling the field inside the parameter * value * @param gap The gap in whose parameter the flow ends * @return The sink object */ public FlowSink createParameterSink(int paraIdx, AccessPath accessPath, GapDefinition gap) { if (accessPath.isLocal()) { if (gap == null && !accessPath.getTaintSubFields() && !(accessPath.getBaseType() instanceof ArrayType)) throw new RuntimeException("Parameter locals cannot directly be sinks"); else return new FlowSink(SourceSinkType.Parameter, paraIdx, accessPath.getBaseType().toString(), accessPath.getTaintSubFields(), gap); } else if (accessPath.getFieldCount() < summaryAPLength) return new FlowSink(SourceSinkType.Parameter, paraIdx, accessPath.getBaseType().toString(), sootFieldsToString(accessPath.getFields()), sootTypesToString(accessPath.getFieldTypes()), accessPath.getTaintSubFields(), gap, false); else return new FlowSink(SourceSinkType.Parameter, paraIdx, accessPath.getBaseType().toString(), sootFieldsToString(cutAPLength(accessPath.getFields())), sootTypesToString(cutAPLength(accessPath.getFieldTypes())), true, gap, false); }
ap.getTaintSubFields())); ap.getTaintSubFields())); ap.getTaintSubFields()));
res.add(new Taint(SourceSinkType.Field, -1, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields(), gap)); res.add(new Taint(SourceSinkType.Parameter, paramIdx, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields(), gap)); res.add(new Taint(SourceSinkType.Return, -1, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields(), gap));
if (curAP.getTaintSubFields() || field == null) return manager.getAccessPathFactory().createAccessPath(base, new SootField[] { field }, true); curAP.getBaseType(), cutFieldTypes, curAP.getTaintSubFields(), false, false, curAP.getArrayTaintType());
/** * Creates a sink that models a value assigned to a field reachable through a * parameter value. This variant models a gap inside the method to be summarized * * @param paraIdx The index of the parameter * @param accessPath The access path modeling the field inside the parameter * value * @return The sink object */ public FlowSink createParameterSinkAtGap(int paraIdx, AccessPath accessPath, String gapSignature) { if (accessPath.isLocal()) { if (!(accessPath.getBaseType() instanceof ArrayType)) throw new RuntimeException("Parameter locals cannot directly be sinks"); else return new FlowSink(SourceSinkType.Parameter, paraIdx, accessPath.getBaseType().toString(), accessPath.getTaintSubFields()); } else if (accessPath.getFieldCount() < summaryAPLength) return new FlowSink(SourceSinkType.Parameter, paraIdx, accessPath.getBaseType().toString(), sootFieldsToString(accessPath.getFields()), sootTypesToString(accessPath.getFieldTypes()), accessPath.getTaintSubFields()); else return new FlowSink(SourceSinkType.Parameter, paraIdx, accessPath.getBaseType().toString(), sootFieldsToString(cutAPLength(accessPath.getFields())), sootTypesToString(cutAPLength(accessPath.getFieldTypes())), true); }
/** * Creates a sink that models the value returned by the method or a field * reachable through the return value. * * @param accessPath The access path modeling the returned value * @param gap The gap to whose return value the data flows * @return The sink object */ public FlowSink createReturnSink(AccessPath accessPath, GapDefinition gap) { if (accessPath.isLocal()) return new FlowSink(SourceSinkType.Return, -1, accessPath.getBaseType().toString(), accessPath.getTaintSubFields(), gap); else if (accessPath.getFieldCount() < summaryAPLength) return new FlowSink(SourceSinkType.Return, -1, accessPath.getBaseType().toString(), sootFieldsToString(accessPath.getFields()), sootTypesToString(accessPath.getFieldTypes()), accessPath.getTaintSubFields(), gap, false); else return new FlowSink(SourceSinkType.Return, -1, accessPath.getBaseType().toString(), sootFieldsToString(cutAPLength(accessPath.getFields())), sootTypesToString(cutAPLength(accessPath.getFieldTypes())), true, gap, false); }
/** * Creates a sink that models a value assigned to a field * * @param accessPath The access path modeling the field * @param gap The gap in which this field taint ends * @return The sink object */ public FlowSink createFieldSink(AccessPath accessPath, GapDefinition gap) { if (accessPath.isLocal()) return new FlowSink(SourceSinkType.Field, -1, accessPath.getBaseType().toString(), accessPath.getTaintSubFields(), gap); else if (accessPath.getFieldCount() < summaryAPLength) return new FlowSink(SourceSinkType.Field, -1, accessPath.getBaseType().toString(), sootFieldsToString(accessPath.getFields()), sootTypesToString(accessPath.getFieldTypes()), accessPath.getTaintSubFields(), gap, false); else return new FlowSink(SourceSinkType.Field, -1, accessPath.getBaseType().toString(), sootFieldsToString(cutAPLength(accessPath.getFields())), sootTypesToString(cutAPLength(accessPath.getFieldTypes())), true, gap, false); }
for (int i = 0; i < iexpr.getArgCount(); i++) if (iexpr.getArg(i) == ap.getPlainValue()) { if (ap.getTaintSubFields() || ap.isLocal()) return true;
@Override public SinkInfo getSinkInfo(Stmt sCallSite, InfoflowManager manager, AccessPath ap) { if (!sCallSite.containsInvokeExpr()) return null; SootMethod target = sCallSite.getInvokeExpr().getMethod(); SinkInfo targetInfo = new SinkInfo(new MethodSourceSinkDefinition(new SootMethodAndClass(target))); if ((target.getSignature().equals(sinkAP) || target.getSignature().equals(sinkAP2) || target.getSignature().equals(sink)) && sCallSite.getInvokeExpr().getArgCount() > 0) { if (ap == null) return targetInfo; else if (ap.getPlainValue() == sCallSite.getInvokeExpr().getArg(0)) if (ap.isLocal() || ap.getTaintSubFields()) return targetInfo; } return null; }
for (int i = 0; i < iexpr.getArgCount(); i++) { if (getAliasing().mayAlias(iexpr.getArg(i), apBaseValue)) { if (source.getAccessPath().getTaintSubFields() || source.getAccessPath().isLocal()) return true;
@Override public Collection<Abstraction> propagateReturnFlow(Collection<Abstraction> callerD1s, Abstraction source, Stmt stmt, Stmt retSite, Stmt callSite, ByReferenceBoolean killAll) { // Check whether this return is treated as a sink if (stmt instanceof ReturnStmt) { final ReturnStmt returnStmt = (ReturnStmt) stmt; boolean matches = source.getAccessPath().isLocal() || source.getAccessPath().getTaintSubFields(); if (matches && source.isAbstractionActive() && getManager().getSourceSinkManager() != null && getAliasing().mayAlias(source.getAccessPath().getPlainValue(), returnStmt.getOp())) { SinkInfo sinkInfo = getManager().getSourceSinkManager().getSinkInfo(returnStmt, getManager(), source.getAccessPath()); if (sinkInfo != null && !getResults().addResult(new AbstractionAtSink(sinkInfo.getDefinition(), source, returnStmt))) killState = true; } } // If we are in the kill state, we stop the analysis if (killAll != null) killAll.value |= killState; return null; }
for (int i = 0; i < iexpr.getArgCount(); i++) if (iexpr.getArg(i) == ap.getPlainValue()) { if (ap.getTaintSubFields() || ap.isLocal()) return new SinkInfo(new MethodSourceSinkDefinition(smac));
if (obj != null && obj.getAccessPath().getTaintSubFields()) {