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

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

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

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.StringConcat;
import it.unive.lisa.symbolic.value.operator.binary.StringContains;
import it.unive.lisa.symbolic.value.operator.binary.StringEndsWith;
import it.unive.lisa.symbolic.value.operator.binary.StringEquals;
import it.unive.lisa.symbolic.value.operator.binary.StringIndexOf;
import it.unive.lisa.symbolic.value.operator.binary.StringStartsWith;
import it.unive.lisa.symbolic.value.operator.ternary.StringReplace;
import it.unive.lisa.symbolic.value.operator.ternary.TernaryOperator;
import it.unive.lisa.util.numeric.IntInterval;
import it.unive.lisa.util.numeric.MathNumber;
import it.unive.lisa.util.representation.StringRepresentation;
import it.unive.lisa.util.representation.StructuredRepresentation;
import java.util.Objects;

/**
 * The suffix string abstract domain.
 *
 * @author Vincenzo Arceri
 * @author Sergio
 *             Salvatore Evola
 * 
 * @see 
 *          https://link.springer.com/chapter/10.1007/978-3-642-24559-6_34
 */
public class Suffix implements BaseNonRelationalValueDomain, ContainsCharProvider {

	private final static Suffix TOP = new Suffix();
	private final static Suffix BOTTOM = new Suffix(null);
	private final String suffix;

	/**
	 * Builds the top suffix abstract element.
	 */
	public Suffix() {
		this("");
	}

	/**
	 * Builds a suffix abstract element.
	 *
	 * @param suffix the suffix
	 */
	public Suffix(
			String suffix) {
		this.suffix = suffix;
	}

	@Override
	public Suffix lubAux(
			Suffix other)
			throws SemanticException {
		String otherSuffix = other.suffix;
		StringBuilder result = new StringBuilder();

		int i = suffix.length() - 1;
		int j = otherSuffix.length() - 1;

		while (i >= 0 && j >= 0 &&
				suffix.charAt(i) == otherSuffix.charAt(j)) {
			result.append(suffix.charAt(i--));
			j--;
		}

		if (result.length() != 0)
			return new Suffix(result.reverse().toString());

		else
			return TOP;
	}

	@Override
	public boolean lessOrEqualAux(
			Suffix other)
			throws SemanticException {
		if (other.suffix.length() <= this.suffix.length()) {
			Suffix lub = this.lubAux(other);

			return lub.suffix.length() == other.suffix.length();
		}

		return false;
	}

	@Override
	public boolean equals(
			Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;
		Suffix suffix1 = (Suffix) o;
		return Objects.equals(suffix, suffix1.suffix);
	}

	@Override
	public int hashCode() {
		return Objects.hash(suffix);
	}

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

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

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

		return new StringRepresentation('*' + suffix);
	}

	@Override
	public Suffix evalNonNullConstant(
			Constant constant,
			ProgramPoint pp,
			SemanticOracle oracle) {
		if (constant.getValue() instanceof String) {
			String str = (String) constant.getValue();
			if (!str.isEmpty())
				return new Suffix(str);
		}

		return TOP;
	}

	@Override
	public Suffix evalBinaryExpression(
			BinaryOperator operator,
			Suffix left,
			Suffix right,
			ProgramPoint pp,
			SemanticOracle oracle) {
		if (operator == StringConcat.INSTANCE) {
			return right;
		} else if (operator == StringContains.INSTANCE ||
				operator == StringEndsWith.INSTANCE ||
				operator == StringEquals.INSTANCE ||
				operator == StringIndexOf.INSTANCE ||
				operator == StringStartsWith.INSTANCE) {
			return TOP;
		}

		return TOP;
	}

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

		if (operator == StringReplace.INSTANCE) {
			String replace = right.getSuffix();
			String string = middle.getSuffix();
			String target = left.getSuffix();

			if (!target.contains(replace))
				return this;

			return new Suffix(target.replace(replace, string));
		}

		return TOP;
	}

	/**
	 * Yields the suffix of this abstract value.
	 *
	 * @return the suffix of this abstract value.
	 */
	public String getSuffix() {
		return this.suffix;
	}

	/**
	 * Yields the suffix corresponding to the substring of this suffix between
	 * two indexes.
	 * 
	 * @param begin where the substring starts
	 * @param end   where the substring ends
	 * 
	 * @return the suffix corresponding to the substring of this suffix between
	 *             two indexes
	 */
	public Suffix substring(
			long begin,
			long end) {
		return new Suffix("");
	}

	/**
	 * Yields the {@link IntInterval} containing the minimum and maximum length
	 * of this abstract value.
	 * 
	 * @return the minimum and maximum length of this abstract value
	 */
	public IntInterval length() {
		return new IntInterval(new MathNumber(suffix.length()), MathNumber.PLUS_INFINITY);
	}

	/**
	 * Yields the {@link IntInterval} containing the minimum and maximum index
	 * of {@code s} in {@code this}.
	 *
	 * @param s the string to be searched
	 * 
	 * @return the minimum and maximum index of {@code s} in {@code this}
	 */
	public IntInterval indexOf(
			Suffix s) {
		return new IntInterval(MathNumber.MINUS_ONE, MathNumber.PLUS_INFINITY);
	}

	@Override
	public Satisfiability containsChar(
			char c) {
		if (isTop())
			return Satisfiability.UNKNOWN;
		if (isBottom())
			return Satisfiability.BOTTOM;
		return this.suffix.contains(String.valueOf(c)) ? Satisfiability.SATISFIED : Satisfiability.UNKNOWN;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy