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

boomerang.weights.PathConditionWeight Maven / Gradle / Ivy

There is a newer version: 3.2.2
Show newest version
package boomerang.weights;

import boomerang.scene.Method;
import boomerang.scene.Statement;
import boomerang.scene.Val;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.Map;
import java.util.Set;
import wpds.impl.Weight;

public class PathConditionWeight extends Weight {

  private static PathConditionWeight one;
  private Map ifStatements = Maps.newHashMap();
  private Map variableToValue = Maps.newHashMap();
  private Set returnVals = Sets.newHashSet();
  private Map calleeToCallSite = Maps.newHashMap();
  private String rep;

  private PathConditionWeight(String rep) {
    this.rep = rep;
  }

  public PathConditionWeight(Statement callSite, Method callee) {
    this.calleeToCallSite.put(callee, callSite);
  }

  public static PathConditionWeight one() {
    if (one == null) {
      one = new PathConditionWeight("ONE");
    }
    return one;
  }

  public PathConditionWeight(Val returnVal) {
    this.returnVals.add(returnVal);
  }

  private PathConditionWeight(
      Map ifStatements,
      Map variableToValue,
      Set returnVals,
      Map calleeToCallSiteMapping) {
    this.ifStatements = ifStatements;
    this.variableToValue = variableToValue;
    this.returnVals = returnVals;
    this.calleeToCallSite = calleeToCallSiteMapping;
  }

  public PathConditionWeight(Statement ifStatement, Boolean condition) {
    ifStatements.put(ifStatement, condition ? ConditionDomain.TRUE : ConditionDomain.FALSE);
  }

  public PathConditionWeight(Val val, ConditionDomain c) {
    variableToValue.put(val, c);
  }

  public enum ConditionDomain {
    TRUE,
    FALSE,
    TOP
  }

  @Override
  public Weight extendWith(Weight o) {
    if (!(o instanceof PathConditionWeight)) {
      throw new RuntimeException("Cannot extend to different types of weight!");
    }
    PathConditionWeight other = (PathConditionWeight) o;
    Map newIfs = Maps.newHashMap();

    newIfs.putAll(ifStatements);
    for (Map.Entry e : other.ifStatements.entrySet()) {
      if (newIfs.containsKey(e.getKey()) && e.getValue().equals(ConditionDomain.TOP)) {
        newIfs.put(e.getKey(), ConditionDomain.TOP);
      } else {
        newIfs.put(e.getKey(), e.getValue());
      }
    }

    Map newVals = Maps.newHashMap();

    newVals.putAll(variableToValue);
    for (Map.Entry e : other.variableToValue.entrySet()) {
      if (newVals.containsKey(e.getKey()) && e.getValue().equals(ConditionDomain.TOP)) {
        newVals.put(e.getKey(), ConditionDomain.TOP);
      } else {
        newVals.put(e.getKey(), e.getValue());
      }
    }

    // May become a performance bottleneck
    Map returnToAssignedVariableMap = Maps.newHashMap();
    if (!returnVals.isEmpty()) {
      for (Map.Entry v : newVals.entrySet()) {
        if (returnVals.contains(v.getKey())) {
          Statement s = calleeToCallSite.get(v.getKey().m());
          if (s != null && s.isAssign()) {
            Val leftOp = s.getLeftOp();
            returnToAssignedVariableMap.put(leftOp, v.getValue());
          }
        }
      }
    }
    newVals.putAll(returnToAssignedVariableMap);
    Set newReturnVals = Sets.newHashSet(returnVals);
    newReturnVals.addAll(other.returnVals);
    Map calleeToCallSiteMapping = Maps.newHashMap(calleeToCallSite);
    calleeToCallSiteMapping.putAll(other.calleeToCallSite);
    return new PathConditionWeight(newIfs, newVals, newReturnVals, calleeToCallSiteMapping);
  }

  @Override
  public Weight combineWith(Weight o) {
    if (!(o instanceof PathConditionWeight)) {
      throw new RuntimeException("Cannot extend to different types of weight!");
    }
    PathConditionWeight other = (PathConditionWeight) o;
    Map newIfs = Maps.newHashMap();
    for (Map.Entry e : ifStatements.entrySet()) {
      if (other.ifStatements.containsKey(e.getKey())) {
        ConditionDomain otherVal = other.ifStatements.get(e.getKey());
        if (e.getValue().equals(otherVal)) {
          newIfs.put(e.getKey(), otherVal);
        } else {
          newIfs.put(e.getKey(), ConditionDomain.TOP);
        }
      } else {
        newIfs.put(e.getKey(), e.getValue());
      }
    }
    for (Map.Entry e : other.ifStatements.entrySet()) {
      if (!ifStatements.containsKey(e.getKey())) {
        newIfs.put(e.getKey(), e.getValue());
      }
    }

    Map newVals = Maps.newHashMap();
    for (Map.Entry e : variableToValue.entrySet()) {
      if (other.variableToValue.containsKey(e.getKey())) {
        ConditionDomain otherVal = other.variableToValue.get(e.getKey());
        if (e.getValue().equals(otherVal)) {
          newVals.put(e.getKey(), otherVal);
        } else {
          newVals.put(e.getKey(), ConditionDomain.TOP);
        }
      } else {
        newVals.put(e.getKey(), e.getValue());
      }
    }
    for (Map.Entry e : other.variableToValue.entrySet()) {
      if (!variableToValue.containsKey(e.getKey())) {
        newVals.put(e.getKey(), e.getValue());
      }
    }

    Map returnToAssignedVariableMap = Maps.newHashMap();
    if (!returnVals.isEmpty()) {
      for (Map.Entry v : newVals.entrySet()) {
        if (returnVals.contains(v.getKey())) {
          Statement s = calleeToCallSite.get(v.getKey().m());
          if (s != null && s.isAssign()) {
            Val leftOp = s.getLeftOp();
            returnToAssignedVariableMap.put(leftOp, v.getValue());
          }
        }
      }
    }
    newVals.putAll(returnToAssignedVariableMap);
    Set newReturnVals = Sets.newHashSet(returnVals);
    newReturnVals.addAll(other.returnVals);
    Map calleeToCallSiteMapping = Maps.newHashMap(calleeToCallSite);
    calleeToCallSiteMapping.putAll(other.calleeToCallSite);
    return new PathConditionWeight(newIfs, newVals, newReturnVals, calleeToCallSiteMapping);
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((ifStatements == null) ? 0 : ifStatements.hashCode());
    result = prime * result + ((variableToValue == null) ? 0 : variableToValue.hashCode());
    result = prime * result + ((rep == null) ? 0 : rep.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    PathConditionWeight other = (PathConditionWeight) obj;
    if (ifStatements == null) {
      if (other.ifStatements != null) {
        return false;
      }
    } else if (!ifStatements.equals(other.ifStatements)) {
      return false;
    }

    if (variableToValue == null) {
      if (other.variableToValue != null) {
        return false;
      }
    } else if (!variableToValue.equals(other.variableToValue)) {
      return false;
    }
    if (rep == null) {
      if (other.rep != null) {
        return false;
      }
    } else if (!rep.equals(other.rep)) {
      return false;
    }
    return true;
  }

  public Map getConditions() {
    return ifStatements;
  }

  public Map getEvaluationMap() {
    return variableToValue;
  }

  @Override
  public String toString() {
    return "\nIf statements: " + ifStatements + " Vals: " + variableToValue;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy