private AccessPath matchAccessPath(AccessPath curAP, Value base, SootField field) { if (curAP.getPlainValue() != base) return null; if (curAP.isLocal()) { if (curAP.getTaintSubFields() || field == null) return manager.getAccessPathFactory().createAccessPath(base, new SootField[] { field }, true); if (curAP.isInstanceFieldRef()) { if (curAP.getFirstField() == field) { return curAP; } else { SootField[] cutFields = new SootField[curAP.getFieldCount() + xbase.getFields().length]; Type[] cutFieldTypes = new Type[cutFields.length]; System.arraycopy(curAP.getFields(), 0, cutFields, xbase.getFields().length, curAP.getFieldCount()); System.arraycopy(curAP.getFieldTypes(), 0, cutFieldTypes, xbase.getFields().length, curAP.getFieldCount()); return manager.getAccessPathFactory().createAccessPath(curAP.getPlainValue(), cutFields, curAP.getBaseType(), cutFieldTypes, curAP.getTaintSubFields(), false, false, curAP.getArrayTaintType());
/** * Checks whether the given access path can potentially have aliases * @param ap The access path to check * @return True if the given access path can potentially have aliases, * otherwise false */ public static boolean canAccessPathHaveAliases(AccessPath ap) { Type lastType = ap.getLastFieldType(); return lastType instanceof RefType && !((RefType) lastType).getSootClass().getName().equals("java.lang.String"); }
/** * Gets the points-to-set for the given access path * @param accessPath The access path for which to get the points-to-set * @return The points-to-set for the given access path */ private PointsToSet getPointsToSet(AccessPath accessPath) { if (accessPath.isLocal()) return Scene.v().getPointsToAnalysis().reachingObjects(accessPath.getPlainValue()); else if (accessPath.isInstanceFieldRef()) return Scene.v().getPointsToAnalysis().reachingObjects(accessPath.getPlainValue(), accessPath.getFirstField()); else if (accessPath.isStaticFieldRef()) return Scene.v().getPointsToAnalysis().reachingObjects(accessPath.getFirstField()); else throw new RuntimeException("Unexepected access path type"); }
/** * 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()); }
/** * Gets whether the given access path can have aliases * * @param ap The access path to check * @return True if the given access path can have aliases, otherwise false */ public static boolean canHaveAliases(AccessPath ap) { // String cannot have aliases if (TypeUtils.isStringType(ap.getBaseType()) && !ap.getCanHaveImmutableAliases()) return false; // We never ever handle primitives as they can never have aliases if (ap.isStaticFieldRef()) { if (ap.getFirstFieldType() instanceof PrimType) return false; } else if (ap.getBaseType() instanceof PrimType) 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); }
if ((ap.isLocal() || ap.isInstanceFieldRef()) && base != null && base == ap.getPlainValue()) { if (newTaints == null) newTaints = new HashSet<>(); newTaints.add(new Taint(SourceSinkType.Field, -1, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields())); newTaints = new HashSet<>(); newTaints.add(new Taint(SourceSinkType.Parameter, paramIdx, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields())); if (defStmt.getLeftOp() == ap.getPlainValue()) { if (newTaints == null) newTaints = new HashSet<>(); newTaints.add(new Taint(SourceSinkType.Return, -1, ap.getBaseType().toString(), fieldArrayToStringArray(ap.getFields()), typeArrayToStringArray(ap.getFieldTypes()), ap.getTaintSubFields()));
final Collection<BasePair> bases = taintedAP.isStaticFieldRef() ? manager.getAccessPathFactory().getBaseForType(taintedAP.getFirstFieldType()) : manager.getAccessPathFactory().getBaseForType(taintedAP.getBaseType()); if (fieldIdx >= taintedAP.getFieldCount()) { if (taintedAP.getTaintSubFields()) return taintedAP; else if (taintedAP.getFields()[fieldIdx] != referencedFields[fieldIdx]) { if (bases != null && !(taintedAP.isStaticFieldRef() && fieldIdx == 0)) { SootField[] cutFields = new SootField[taintedAP.getFieldCount() + base.getFields().length]; Type[] cutFieldTypes = new Type[cutFields.length]; System.arraycopy(taintedAP.getFields(), 0, cutFields, 0, fieldIdx); System.arraycopy(base.getFields(), 0, cutFields, fieldIdx, base.getFields().length); System.arraycopy(taintedAP.getFields(), fieldIdx, cutFields, 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); return manager.getAccessPathFactory().createAccessPath(taintedAP.getPlainValue(), cutFields, taintedAP.getBaseType(), cutFieldTypes, taintedAP.getTaintSubFields(), false, false, taintedAP.getArrayTaintType());
assert !source.getAccessPath().isEmpty(); if (rightValue instanceof InstanceFieldRef) { InstanceFieldRef ref = (InstanceFieldRef) rightValue; if (source.getAccessPath().isInstanceFieldRef() && ref.getBase() == source.getAccessPath().getPlainValue() && source.getAccessPath().firstFieldMatches(ref.getField())) { AccessPath ap = manager.getAccessPathFactory().copyWithNewValue(source.getAccessPath(), leftValue, source.getAccessPath().getFirstFieldType(), true); newLeftAbs = checkAbstraction(source.deriveNewAbstraction(ap, defStmt)); && rightValue instanceof StaticFieldRef) { StaticFieldRef ref = (StaticFieldRef) rightValue; if (source.getAccessPath().isStaticFieldRef() && source.getAccessPath().firstFieldMatches(ref.getField())) { AccessPath ap = manager.getAccessPathFactory().copyWithNewValue(source.getAccessPath(), leftValue, source.getAccessPath().getBaseType(), true); newLeftAbs = checkAbstraction(source.deriveNewAbstraction(ap, defStmt)); } else if (rightValue == source.getAccessPath().getPlainValue()) { Type newType = source.getAccessPath().getBaseType(); if (leftValue instanceof ArrayRef) { ArrayRef arrayRef = (ArrayRef) leftValue; if (newLeftAbs.getAccessPath().getLastFieldType() instanceof PrimType) return res; if (!newLeftAbs.getAccessPath().equals(source.getAccessPath())) {
if (obj != null && obj.getAccessPath().getTaintSubFields()) { if (obj.getAccessPath().isLocal()) { Type tp = obj.getAccessPath().getPlainValue().getType(); Type runtimeType = obj.getAccessPath().getBaseType(); if (isComponentType(tp) || isComponentType(runtimeType) || isFilteredSystemType(tp) || isFilteredSystemType(runtimeType)) { if (obj.getAccessPath().isInstanceFieldRef()) { Type tp = obj.getAccessPath().getLastField().getType(); Type runtimeType = obj.getAccessPath().getLastFieldType(); if (isComponentType(tp) || isComponentType(runtimeType) || isFilteredSystemType(tp) || isFilteredSystemType(runtimeType)) {
implicitTaint |= newSource.getAccessPath().isEmpty(); if ((d1 == null || d1.getAccessPath().isEmpty()) && !(leftValue instanceof FieldRef)) return Collections.singleton(newSource); if (newSource.getAccessPath().isEmpty()) addLeftValue = true; Local sourceBase = newSource.getAccessPath().getPlainValue(); final SootField rightField = rightRef.getField(); cutFirstField = (mappedAP.getFieldCount() > 0 && mappedAP.getFirstField() == rightField); } else if (aliasing.mayAlias(rightBase, sourceBase) && newSource.getAccessPath().getFieldCount() == 0 && newSource.getAccessPath().getTaintSubFields()) { addLeftValue = true; targetType = rightField.getType(); else if (rightVal instanceof Local && newSource.getAccessPath().isInstanceFieldRef()) { Local base = newSource.getAccessPath().getPlainValue(); if (aliasing.mayAlias(rightVal, base)) { addLeftValue = true; targetType = newSource.getAccessPath().getBaseType(); else if (aliasing.mayAlias(rightVal, newSource.getAccessPath().getPlainValue())) { if (!(assignStmt.getRightOp() instanceof NewArrayExpr)) { if (manager.getConfig().getEnableArraySizeTainting() || !(rightValue instanceof NewArrayExpr)) {
/** * 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(); }
if (accessPath.isStaticFieldRef()) { if (!checkCast(type, accessPath.getFirstFieldType())) return false; if (accessPath.getFieldCount() > 1) return false; fieldStartIdx = 1; } else { if (!checkCast(type, accessPath.getBaseType())) return false; if (!accessPath.isLocal()) return false; if (accessPath.isFieldRef() && accessPath.getFieldCount() > fieldStartIdx) if (!checkCast(type, accessPath.getFields()[fieldStartIdx].getDeclaringClass().getType())) return false;
if ((ap.isInstanceFieldRef() && ap.getFirstField() != null) || (ap.isStaticFieldRef() && ap.getFieldCount() > 1)) { List<SootField> appendList = new LinkedList<SootField>(appendFields); appendList.add(0, newAbs.getAccessPath().getLastField()); List<Type> typesList = new LinkedList<Type>(appendTypes); typesList.add(0, newAbs.getAccessPath().getLastFieldType()); (newAbs.getAccessPath().dropLastField(), null), appendList, typesList, taintSubFields, actStmt); if (ap.getFieldCount() > 1) return; if (invExpr instanceof InstanceInvokeExpr && !newAbs.getAccessPath().isStaticFieldRef()) { InstanceInvokeExpr iinvExpr = (InstanceInvokeExpr) invExpr; PointsToSet ptsBase = getPointsToSet((Local) iinvExpr.getBase()); PointsToSet ptsBaseOrg = getPointsToSet(newAbs.getAccessPath().getPlainValue()); baseAliases = ptsBase.hasNonEmptyIntersection(ptsBaseOrg);
if (!ap.isStaticFieldRef()) { for (int i = 0; i < iexpr.getArgCount(); i++) if (iexpr.getArg(i) == ap.getPlainValue()) { if (ap.getTaintSubFields() || ap.isLocal()) return true; if (((InstanceInvokeExpr) iexpr).getBase() == ap.getPlainValue()) return true;
final Value apBaseValue = source.getAccessPath().getPlainValue(); if (apBaseValue != 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; if (((InstanceInvokeExpr) iexpr).getBase() == source.getAccessPath().getPlainValue()) return true;
if (apAtReturn.getPlainValue() == retStmt.getOp()) { FlowSink sink = sourceSinkFactory.createReturnSink(apAtReturn); addFlow(source, sink, isAlias, flows); if (!apAtReturn.isLocal() || apAtReturn.getTaintSubFields() || apAtReturn.getBaseType() instanceof ArrayType) for (int i = 0; i < m.getParameterCount(); i++) { Local p = m.getActiveBody().getParameterLocal(i); if (apAtReturn.getPlainValue() == p) { FlowSink sink = sourceSinkFactory.createParameterSink(i, apAtReturn); addFlow(source, sink, isAlias, flows); if (!m.isStatic() && apAtReturn.getPlainValue() == m.getActiveBody().getThisLocal()) { FlowSink sink = sourceSinkFactory.createFieldSink(apAtReturn); addFlow(source, sink, isAlias, flows); if (apAtReturn.isInstanceFieldRef()) { Set<GapDefinition> referencedGaps = gapManager.getGapDefinitionsForLocalUse(apAtReturn.getPlainValue()); if (referencedGaps != null && !referencedGaps.isEmpty()) for (GapDefinition gap : referencedGaps) { referencedGaps = gapManager.getGapDefinitionsForLocalDef(apAtReturn.getPlainValue()); if (referencedGaps != null && !referencedGaps.isEmpty()) for (GapDefinition gap : referencedGaps) {
if (!AccessPath.canContainValue(val)) return null; if (ap.getPlainValue() != val) return null; if (ap.getPlainValue() != ((ArrayRef) val).getBase()) return null; if (!ap.isLocal() && !ap.isInstanceFieldRef()) return null; if (((InstanceFieldRef) val).getBase() != ap.getPlainValue()) return null; if (!ap.isStaticFieldRef()) return null;
/** * 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()); }