All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.rivulet.internal.TaintedSinkValueSet Maven / Gradle / Ivy

The newest version!
package io.rivulet.internal;

import java.util.*;

/* Stores information about a set of tainted values that were passed as arguments to a sink method at a particular
 * argument index. Used to help with merging violations that are the same except for their sinkValues. */
public class TaintedSinkValueSet extends TaintedSinkValue {

    private static final long serialVersionUID = 4570655916959523458L;
    // Text representations of the tainted values that reached the sink
    private final TreeSet sinkValues;

    /* Constructs a new TaintedSinkValueSet with the information from the specified TaintedSinkValue Converts all of the
     * taintSource labels of the specified TaintedSinkValue into ProcessedSourceInfoTaintLabels. */
    private TaintedSinkValueSet(TaintedSinkValue value) {
        super(value.getSinkValueClass(), value.getSinkArgIndex());
        for(SourceInfoTaintLabel label : value.getTaintSources()) {
            getTaintSources().add(new ProcessedSourceInfoTaintLabel(label));
        }
        this.sinkValues = new TreeSet<>();
    }

    /* Getter for sinkValues. */
    public List getSinkValues() {
        return new LinkedList<>(sinkValues);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        TaintedSinkValueSet that = (TaintedSinkValueSet) o;
        return sinkValues.equals(that.sinkValues);
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + sinkValues.hashCode();
        return result;
    }

    /* Adds indexInfo information from the labels of the specified actualValue to the labels of the specified baseValue. */
    private static void mergeIndexInfo(TaintedSinkValueSet baseValue, TaintedSinkValueImpl actualValue) {
        LinkedHashSet baseSources = baseValue.getTaintSources();
        LinkedHashSet actualSources = actualValue.getTaintSources();
        for(SourceInfoTaintLabel actualLabel : actualSources) {
            if(actualLabel instanceof IndexedSourceInfoTaintLabel) {
                InvocationRanges indexInfo = ((IndexedSourceInfoTaintLabel) actualLabel).getIndexInfoCopy();
                for(SourceInfoTaintLabel baseLabel : baseSources) {
                    if(baseLabel instanceof ProcessedSourceInfoTaintLabel && ((ProcessedSourceInfoTaintLabel) baseLabel).baseInfoMatches(actualLabel)) {
                        ((ProcessedSourceInfoTaintLabel) baseLabel).addIndexInfo(indexInfo);
                    }
                }
            }
        }
    }

    /* Merges the specified list of actualSets which match the specified baseSet into a single set. */
    private static LinkedHashSet mergeTaintedValues(LinkedHashSet baseSet, LinkedList> actualSets) {
        // Map each base TaintedSinkValueImpl to a TaintedSinkValueSet created from it
        LinkedHashMap map = new LinkedHashMap<>();
        for(TaintedSinkValueImpl baseImpl : baseSet) {
            map.put(baseImpl, new TaintedSinkValueSet(baseImpl));
        }
        // Extract information from the actual sets
        for(LinkedHashSet actualSet : actualSets) {
            for(TaintedSinkValueImpl actualImpl : actualSet) {
                TaintedSinkValueSet match = map.get(actualImpl.copyWithoutSinkValueOrIndexInfo());
                // Add sinkValue information
                match.sinkValues.add(actualImpl.getSinkValue());
                // Add indexInfo information to the labels
                mergeIndexInfo(match, actualImpl);
            }
        }
        return new LinkedHashSet<>(map.values());
    }

    /* Merges violations that are the same except for their sinkValues and indexInfo together. Returns a mapping from
     * these merged violation to lists of the original violations that were merged to form them. */
    public static LinkedHashMap> mergeViolations(Iterable violations) {
        // Maps base violations (violations with their taintedValues removed) to a mapping between sets of base TaintedSinkValueImpls
        // (TaintedSinkValueImpl with their sinkValue and indexInfo removed) to a list of sets TaintedSinkValueImpls that match
        // the base TaintedSinkValueImpl set
        LinkedHashMap, LinkedList>>> map = new LinkedHashMap<>();
        LinkedHashMap, LinkedList>> originalViolationMap = new LinkedHashMap<>();
        for(Violation v : violations) {
            Violation baseViolation = v.copyWithTaintedValues(new LinkedHashSet<>());
            map.putIfAbsent(baseViolation, new LinkedHashMap<>());
            originalViolationMap.putIfAbsent(baseViolation, new LinkedHashMap<>());
            LinkedHashMap, LinkedList>> baseToActualSetMap = map.get(baseViolation);
            LinkedHashMap, LinkedList> baseSetToOriginalViolationMap = originalViolationMap.get(baseViolation);
            LinkedHashSet baseSet = new LinkedHashSet<>();
            LinkedHashSet actualSet = new LinkedHashSet<>();
            for(TaintedSinkValue value : v.getTaintedValues()) {
                if(value instanceof TaintedSinkValueImpl) {
                    baseSet.add(((TaintedSinkValueImpl)value).copyWithoutSinkValueOrIndexInfo());
                    actualSet.add((TaintedSinkValueImpl)value);
                }
            }
            baseToActualSetMap.putIfAbsent(baseSet, new LinkedList<>());
            baseToActualSetMap.get(baseSet).add(actualSet);
            baseSetToOriginalViolationMap.putIfAbsent(baseSet, new LinkedList<>());
            baseSetToOriginalViolationMap.get(baseSet).add(v);
        }
        LinkedHashMap>  result = new LinkedHashMap<>();
        for(Violation baseViolation : map.keySet()) {
            for(LinkedHashSet baseSet : map.get(baseViolation).keySet()) {
                Violation mergedViolation = baseViolation.copyWithTaintedValues(mergeTaintedValues(baseSet, map.get(baseViolation).get(baseSet)));
                result.put(mergedViolation, originalViolationMap.get(baseViolation).get(baseSet));
            }
        }
        return result;
    }

    /* Returns a copy of the specified violation but with it's taintedValues merged. */
    public static Violation processViolation(Violation violation) {
        // Map each base TaintedSinkValueImpl to a TaintedSinkValueSet created from it
        LinkedHashMap map = new LinkedHashMap<>();
        for(TaintedSinkValue value : violation.getTaintedValues()) {
            if(value instanceof TaintedSinkValueImpl) {
                TaintedSinkValueImpl valueImpl = (TaintedSinkValueImpl) value;
                TaintedSinkValueImpl base = valueImpl.copyWithoutSinkValueOrIndexInfo();
                if(!map.containsKey(base)) {
                    map.put(base, new TaintedSinkValueSet(valueImpl));
                }
                map.get(base).sinkValues.add(valueImpl.getSinkValue());
                mergeIndexInfo(map.get(base), valueImpl);
            }
        }
        return violation.copyWithTaintedValues(map.values());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy