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

it.unive.lisa.analysis.string.StringConstantPropagation Maven / Gradle / Ivy

The newest version!
package it.unive.lisa.analysis.string;

import it.unive.lisa.analysis.BaseLattice;
import it.unive.lisa.analysis.Lattice;
import it.unive.lisa.analysis.SemanticException;
import it.unive.lisa.analysis.SemanticOracle;
import it.unive.lisa.analysis.lattices.Satisfiability;
import it.unive.lisa.analysis.nonrelational.value.BaseNonRelationalValueDomain;
import it.unive.lisa.program.cfg.ProgramPoint;
import it.unive.lisa.symbolic.value.Constant;
import it.unive.lisa.symbolic.value.operator.binary.BinaryOperator;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonEq;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonGe;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonGt;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonLe;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonLt;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonNe;
import it.unive.lisa.symbolic.value.operator.binary.StringConcat;
import it.unive.lisa.symbolic.value.operator.ternary.StringReplace;
import it.unive.lisa.symbolic.value.operator.ternary.TernaryOperator;
import it.unive.lisa.symbolic.value.operator.unary.UnaryOperator;
import it.unive.lisa.util.representation.StringRepresentation;
import it.unive.lisa.util.representation.StructuredRepresentation;

/**
 * The string constant propagation abstract domain, tracking if a certain string
 * value has constant value or not. Top and bottom cases for least upper bounds,
 * widening and less or equals operations are handled by {@link BaseLattice} in
 * {@link BaseLattice#lub}, {@link BaseLattice#widening} and
 * {@link BaseLattice#lessOrEqual}, respectively.
 * 
 * @author Michele
 *             Martelli
 * @author Vincenzo Arceri
 */
public class StringConstantPropagation implements BaseNonRelationalValueDomain {

	private static final StringConstantPropagation TOP = new StringConstantPropagation(true, false);
	private static final StringConstantPropagation BOTTOM = new StringConstantPropagation(false, true);

	private final boolean isTop, isBottom;

	private final String value;

	/**
	 * Builds the top abstract value.
	 */
	public StringConstantPropagation() {
		this(null, true, false);
	}

	private StringConstantPropagation(
			String value,
			boolean isTop,
			boolean isBottom) {
		this.value = value;
		this.isTop = isTop;
		this.isBottom = isBottom;
	}

	/**
	 * Builds the abstract value for the given constant.
	 * 
	 * @param value the constant
	 */
	public StringConstantPropagation(
			String value) {
		this(value, false, false);
	}

	private StringConstantPropagation(
			boolean isTop,
			boolean isBottom) {
		this(null, isTop, isBottom);
	}

	@Override
	public StringConstantPropagation top() {
		return TOP;
	}

	@Override
	public boolean isTop() {
		return isTop;
	}

	@Override
	public StringConstantPropagation bottom() {
		return BOTTOM;
	}

	@Override
	public StructuredRepresentation representation() {
		if (isBottom())
			return Lattice.bottomRepresentation();
		if (isTop())
			return Lattice.topRepresentation();

		return new StringRepresentation(value);
	}

	@Override
	public StringConstantPropagation evalNullConstant(
			ProgramPoint pp,
			SemanticOracle oracle) {
		return top();
	}

	@Override
	public StringConstantPropagation evalNonNullConstant(
			Constant constant,
			ProgramPoint pp,
			SemanticOracle oracle) {
		if (constant.getValue() instanceof String)
			return new StringConstantPropagation((String) constant.getValue());

		return top();
	}

	@Override
	public StringConstantPropagation evalUnaryExpression(
			UnaryOperator operator,
			StringConstantPropagation arg,
			ProgramPoint pp,
			SemanticOracle oracle) {

		return top();
	}

	@Override
	public StringConstantPropagation evalBinaryExpression(
			BinaryOperator operator,
			StringConstantPropagation left,
			StringConstantPropagation right,
			ProgramPoint pp,
			SemanticOracle oracle) {

		if (operator instanceof StringConcat)
			return left.isTop() || right.isTop() ? top() : new StringConstantPropagation(left.value + right.value);

		return top();
	}

	@Override
	public StringConstantPropagation evalTernaryExpression(
			TernaryOperator operator,
			StringConstantPropagation left,
			StringConstantPropagation middle,
			StringConstantPropagation right,
			ProgramPoint pp,
			SemanticOracle oracle) {

		if (operator instanceof StringReplace) {
			if (left.isTop() || right.isTop() || middle.isTop())
				return top();

			String replaced = left.value;
			replaced = replaced.replace(middle.value, right.value);

			return new StringConstantPropagation(replaced);
		}

		return top();

	}

	@Override
	public StringConstantPropagation lubAux(
			StringConstantPropagation other)
			throws SemanticException {
		return TOP;
	}

	@Override
	public boolean lessOrEqualAux(
			StringConstantPropagation other)
			throws SemanticException {
		return false;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (isBottom ? 1231 : 1237);
		result = prime * result + (isTop ? 1231 : 1237);
		result = prime * result + ((value == null) ? 0 : value.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;
		StringConstantPropagation other = (StringConstantPropagation) obj;
		if (isBottom != other.isBottom)
			return false;
		if (isTop != other.isTop)
			return false;
		if (value == null) {
			if (other.value != null)
				return false;
		} else if (!value.equals(other.value))
			return false;
		return true;
	}

	@Override
	public Satisfiability satisfiesBinaryExpression(
			BinaryOperator operator,
			StringConstantPropagation left,
			StringConstantPropagation right,
			ProgramPoint pp,
			SemanticOracle oracle) {

		if (left.isTop() || right.isTop())
			return Satisfiability.UNKNOWN;

		if (operator == ComparisonEq.INSTANCE)
			return left.value.equals(right.value) ? Satisfiability.SATISFIED
					: Satisfiability.NOT_SATISFIED;
		else if (operator == ComparisonGe.INSTANCE)
			return left.value.compareTo(right.value) >= 0 ? Satisfiability.SATISFIED : Satisfiability.NOT_SATISFIED;
		else if (operator == ComparisonGt.INSTANCE)
			return left.value.compareTo(right.value) > 0 ? Satisfiability.SATISFIED : Satisfiability.NOT_SATISFIED;
		else if (operator == ComparisonLe.INSTANCE)
			return left.value.compareTo(right.value) <= 0 ? Satisfiability.SATISFIED : Satisfiability.NOT_SATISFIED;
		else if (operator == ComparisonLt.INSTANCE)
			return left.value.compareTo(right.value) < 0 ? Satisfiability.SATISFIED : Satisfiability.NOT_SATISFIED;
		else if (operator == ComparisonNe.INSTANCE)
			return !left.value.equals(right.value) ? Satisfiability.SATISFIED
					: Satisfiability.NOT_SATISFIED;

		else
			return Satisfiability.UNKNOWN;
	}

	/**
	 * Returns the abstract value of the domain.
	 * 
	 * @return the string representing the constant value
	 * 
	 * @throws SemanticException if the method is called on a top or bottom
	 *                               element
	 */
	protected String getValue() throws SemanticException {
		if (isTop() || isBottom())
			throw new SemanticException("The abstract domain is top or bottom; can't get the constant value");

		return value;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy