/** * 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(); }
/** * Appends additional fields to the given access path * * @param original The original access path to which to append the fields * @param apFields The fields to append * @param apFieldTypes The types of the fields to append * @param taintSubFields True if the new access path shall taint all objects * reachable through it, false if it shall only point to * precisely one object * @return The new access path */ public AccessPath appendFields(AccessPath original, SootField[] apFields, Type[] apFieldTypes, boolean taintSubFields) { int offset = original.getFields() == null ? 0 : original.getFields().length; SootField[] fields = new SootField[offset + (apFields == null ? 0 : apFields.length)]; Type[] fieldTypes = new Type[offset + (apFields == null ? 0 : apFields.length)]; if (original.getFields() != null) { System.arraycopy(original.getFields(), 0, fields, 0, original.getFields().length); System.arraycopy(original.getFieldTypes(), 0, fieldTypes, 0, original.getFieldTypes().length); } if (apFields != null && apFields.length > 0) { System.arraycopy(apFields, 0, fields, offset, apFields.length); System.arraycopy(apFieldTypes, 0, fieldTypes, offset, apFieldTypes.length); } return createAccessPath(original.getPlainValue(), fields, original.getBaseType(), fieldTypes, taintSubFields, false, true, original.getArrayTaintType()); }
/** * 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 new source model based on the given information * * @param type The type of data flow source * @param parameterIdx The index of the method parameter through which the * source value was obtained * @param accessPath The access path describing the exact source object * @param gap The gap from which this flow originated. Null if this * flow did not originate from a gap. * @return The newly created source object */ public FlowSource createSource(SourceSinkType type, int parameterIdx, AccessPath accessPath, GapDefinition gap) { return new FlowSource(type, parameterIdx, accessPath.getBaseType().toString(), sootFieldsToString(cutAPLength(accessPath.getFields())), sootTypesToString(cutAPLength(accessPath.getFieldTypes())), gap); }
fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields())); fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields())); fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields()));
res = new HashSet<>(); res.add(new Taint(SourceSinkType.Field, -1, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields(), gap)); res = new HashSet<>(); res.add(new Taint(SourceSinkType.Parameter, paramIdx, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields(), gap)); res = new HashSet<>(); res.add(new Taint(SourceSinkType.Return, -1, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields(), gap));
fieldIdx + base.getFields().length, taintedAP.getFieldCount() - fieldIdx); System.arraycopy(taintedAP.getFieldTypes(), 0, cutFieldTypes, 0, fieldIdx); System.arraycopy(base.getTypes(), 0, cutFieldTypes, fieldIdx, base.getTypes().length); System.arraycopy(taintedAP.getFieldTypes(), fieldIdx, cutFieldTypes, fieldIdx + base.getTypes().length, taintedAP.getFieldCount() - fieldIdx);
/** * 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 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); }
/** * 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); }
System.arraycopy(curAP.getFieldTypes(), 0, cutFieldTypes, xbase.getFields().length, curAP.getFieldCount());