![JAR search and dependency download from the Maven repository](/logo.png)
org.evosuite.symbolic.vm.SymbolicHeap Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
* contributors
*
* This file is part of EvoSuite.
*
* EvoSuite is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* EvoSuite is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EvoSuite. If not, see .
*/
package org.evosuite.symbolic.vm;
import java.util.HashMap;
import java.util.Map;
import org.evosuite.symbolic.expr.Expression;
import org.evosuite.symbolic.expr.bv.IntegerValue;
import org.evosuite.symbolic.expr.fp.RealValue;
import org.evosuite.symbolic.expr.ref.ReferenceConstant;
import org.evosuite.symbolic.expr.ref.ReferenceExpression;
import org.evosuite.symbolic.expr.ref.ReferenceVariable;
import org.evosuite.symbolic.expr.str.StringValue;
import org.objectweb.asm.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author galeotti
*
*/
public final class SymbolicHeap {
protected static final Logger logger = LoggerFactory.getLogger(SymbolicHeap.class);
private static final class FieldKey {
private String owner;
private String name;
public FieldKey(String owner, String name) {
this.owner = owner;
this.name = name;
}
@Override
public int hashCode() {
return this.owner.hashCode() + this.name.hashCode();
}
@Override
public boolean equals(Object o) {
if (o != null && o.getClass().equals(FieldKey.class)) {
FieldKey that = (FieldKey) o;
return this.owner.equals(that.owner) && this.name.equals(that.name);
} else {
return false;
}
}
@Override
public String toString() {
return this.owner + "/" + this.name;
}
}
/**
* Counter for instances
*/
private int newInstanceCount = 0;
/**
* This constructor is for references created in instrumented code (NEW,
* ANEW, NEWARRAY, etc).
*
* It is the only way of creating uninitialized non-null references.
*
* @param exceptionClassName
*
* @return
*/
public ReferenceConstant buildNewReferenceConstant(Type objectType) {
if (objectType.getClassName() == null)
throw new IllegalArgumentException();
final int newInstanceId = newInstanceCount++;
return new ReferenceConstant(objectType, newInstanceId);
}
/**
* Stores a mapping between identityHashCodes and NonNullReferences. Every
* time the NonNullReference for a given Object (non String) is needed, this
* mapping is used.
*
*/
private final Map nonNullRefs = new HashMap();
/**
* Stores a mapping between NonNullReferences and their symbolic values. The
* Expression> contains at least one symbolic variable.
*/
private final Map>> symb_fields = new HashMap>>();
/**
* Mapping between for symbolic values stored in static fields. The
* Expression> contains at least one symbolic variable.
*/
private final Map> symb_static_fields = new HashMap>();
/**
* Updates an instance field. The symbolic expression is stored iif it is
* not a constant expression (i.e. it has at least one variable).
*
* @param className
* @param fieldName
* @param conc_receiver
* The concrete Object receiver instance
* @param symb_receiver
* A symbolic NonNullReference instance
* @param symb_value
* The Expression to be stored. Null value means the previous
* symbolic expression has to be erased.
*/
public void putField(String className, String fieldName, Object conc_receiver, ReferenceExpression symb_receiver,
Expression> symb_value) {
Map> symb_field = getOrCreateSymbolicField(className, fieldName);
if (symb_value == null || !symb_value.containsSymbolicVariable()) {
symb_field.remove(symb_receiver);
} else {
symb_field.put(symb_receiver, symb_value);
}
}
private Map> getOrCreateSymbolicField(String owner, String name) {
FieldKey k = new FieldKey(owner, name);
Map> symb_field = symb_fields.get(k);
if (symb_field == null) {
symb_field = new HashMap>();
symb_fields.put(k, symb_field);
}
return symb_field;
}
/**
* Returns a stored symbolic expression for an int field or created one
*
* @param owner
* @param name
* @param conc_receiver
* @param symb_receiver
* @param conc_value
* @return
*/
public IntegerValue getField(String owner, String name, Object conc_receiver, ReferenceExpression symb_receiver,
long conc_value) {
Map> symb_field = getOrCreateSymbolicField(owner, name);
IntegerValue symb_value = (IntegerValue) symb_field.get(symb_receiver);
if (symb_value == null || ((Long) symb_value.getConcreteValue()).longValue() != conc_value) {
symb_value = ExpressionFactory.buildNewIntegerConstant(conc_value);
symb_field.remove(symb_receiver);
}
return symb_value;
}
/**
*
* @param className
* @param fieldName
* @param conc_receiver
* @param symb_receiver
* @param conc_value
* @return
*/
public RealValue getField(String className, String fieldName, Object conc_receiver,
ReferenceExpression symb_receiver, double conc_value) {
Map> symb_field = getOrCreateSymbolicField(className, fieldName);
RealValue symb_value = (RealValue) symb_field.get(symb_receiver);
if (symb_value == null || ((Double) symb_value.getConcreteValue()).doubleValue() != conc_value) {
symb_value = ExpressionFactory.buildNewRealConstant(conc_value);
symb_field.remove(symb_receiver);
}
return symb_value;
}
/**
*
* @param className
* @param fieldName
* @param conc_receiver
* @param symb_receiver
* @param conc_value
* @return
*/
public StringValue getField(String className, String fieldName, Object conc_receiver,
ReferenceExpression symb_receiver, String conc_value) {
Map> symb_field = getOrCreateSymbolicField(className, fieldName);
StringValue symb_value = (StringValue) symb_field.get(symb_receiver);
if (symb_value == null || !((String) symb_value.getConcreteValue()).equals(conc_value)) {
symb_value = ExpressionFactory.buildNewStringConstant(conc_value);
symb_field.remove(symb_receiver);
}
return symb_value;
}
/**
* No default concrete value means the return value could be false!
*
* @param className
* @param fieldName
* @param conc_receiver
* @param symb_receiver
* @return
*/
public Expression> getField(String className, String fieldName, Object conc_receiver,
ReferenceExpression symb_receiver) {
Map> symb_field = getOrCreateSymbolicField(className, fieldName);
Expression> symb_value = symb_field.get(symb_receiver);
return symb_value;
}
public void putStaticField(String owner, String name, Expression> symb_value) {
FieldKey k = new FieldKey(owner, name);
if (symb_value == null || !symb_value.containsSymbolicVariable()) {
symb_static_fields.remove(k);
} else {
symb_static_fields.put(k, symb_value);
}
}
public IntegerValue getStaticField(String owner, String name, long conc_value) {
FieldKey k = new FieldKey(owner, name);
IntegerValue symb_value = (IntegerValue) symb_static_fields.get(k);
if (symb_value == null || ((Long) symb_value.getConcreteValue()).longValue() != conc_value) {
symb_value = ExpressionFactory.buildNewIntegerConstant(conc_value);
symb_static_fields.remove(k);
}
return symb_value;
}
public RealValue getStaticField(String owner, String name, double conc_value) {
FieldKey k = new FieldKey(owner, name);
RealValue symb_value = (RealValue) symb_static_fields.get(k);
if (symb_value == null || ((Double) symb_value.getConcreteValue()).doubleValue() != conc_value) {
symb_value = ExpressionFactory.buildNewRealConstant(conc_value);
symb_static_fields.remove(k);
}
return symb_value;
}
public StringValue getStaticField(String owner, String name, String conc_value) {
FieldKey k = new FieldKey(owner, name);
StringValue symb_value = (StringValue) symb_static_fields.get(k);
if (symb_value == null || !((String) symb_value.getConcreteValue()).equals(conc_value)) {
symb_value = ExpressionFactory.buildNewStringConstant(conc_value);
symb_static_fields.remove(k);
}
return symb_value;
}
/**
* Returns a ReferenceConstant
if the concrete reference is
* null. Otherwise, it looks in the list of non-null symbolic references for
* a symbolic reference with the concrete value. If it is found, that
* symbolic reference is returned, otherwise a new reference constant is
* created (and added ot the list of non-null symbolic references)
*
* @param conc_ref
* @return
*/
public ReferenceExpression getReference(Object conc_ref) {
if (conc_ref == null) {
// null reference
ReferenceConstant nullConstant = ExpressionFactory.buildNewNullExpression();
return nullConstant;
} else {
int identityHashCode = System.identityHashCode(conc_ref);
if (nonNullRefs.containsKey(identityHashCode)) {
// already known object
ReferenceExpression symb_ref = nonNullRefs.get(identityHashCode);
return symb_ref;
} else {
// unknown object
final Type type = Type.getType(conc_ref.getClass());
ReferenceConstant ref_constant = new ReferenceConstant(type, newInstanceCount++);
ref_constant.initializeReference(conc_ref);
nonNullRefs.put(identityHashCode, ref_constant);
return ref_constant;
}
}
}
/**
* Builds a new reference variable using a var_name and a concrete obhect
* The concrete object can be null.
*
* @param conc_object
* @param var_name
* @return
*/
public ReferenceVariable buildNewReferenceVariable(Object conc_object, String var_name) {
final Type referenceType;
if (conc_object == null) {
referenceType = Type.getType(Object.class);
} else {
referenceType = Type.getType(conc_object.getClass());
}
final int newInstanceId = newInstanceCount++;
final ReferenceVariable r = new ReferenceVariable(referenceType, newInstanceId, var_name, conc_object);
return r;
}
public void array_store(Object conc_array, ReferenceExpression symb_array, int conc_index,
Expression> symb_value) {
Map> symb_array_contents = getOrCreateSymbolicArray(symb_array);
if (symb_value == null || !symb_value.containsSymbolicVariable()) {
symb_array_contents.remove(conc_index);
} else {
symb_array_contents.put(conc_index, symb_value);
}
}
private final Map>> symb_arrays = new HashMap>>();
public static final String $STRING_BUILDER_CONTENTS = "$stringBuilder_contents";
public static final String $STRING_BUFFER_CONTENTS = "$stringBuffer_contents";
public static final String $BIG_INTEGER_CONTENTS = "$bigInteger_contents";
public static final String $STRING_TOKENIZER_VALUE = "$stringTokenizerValue";
public static final String $STRING_READER_VALUE = "$stringReaderValue";
public static final String $MATCHER_INPUT = "$matcherInput";
public static final String $BOOLEAN_VALUE = "$booleanValue";
public static final String $BYTE_VALUE = "$byteValue";
public static final String $CHAR_VALUE = "$charValue";
public static final String $SHORT_VALUE = "$shortValue";
public static final String $LONG_VALUE = "$longValue";
public static final String $INT_VALUE = "$intValue";
public static final String $FLOAT_VALUE = "$floatValue";
public static final String $DOUBLE_VALUE = "$doubleValue";
public static final String $STRING_VALUE = "$stringValue";
private Map> getOrCreateSymbolicArray(ReferenceExpression symb_array_ref) {
Map> symb_array_contents = symb_arrays.get(symb_array_ref);
if (symb_array_contents == null) {
symb_array_contents = new HashMap>();
symb_arrays.put(symb_array_ref, symb_array_contents);
}
return symb_array_contents;
}
public StringValue array_load(ReferenceExpression symb_array, int conc_index, String conc_value) {
Map> symb_array_contents = getOrCreateSymbolicArray(symb_array);
StringValue symb_value = (StringValue) symb_array_contents.get(conc_index);
if (symb_value == null || !((String) symb_value.getConcreteValue()).equals(conc_value)) {
symb_value = ExpressionFactory.buildNewStringConstant(conc_value);
symb_array_contents.remove(conc_index);
}
return symb_value;
}
public IntegerValue array_load(ReferenceExpression symb_array, int conc_index, long conc_value) {
Map> symb_array_contents = getOrCreateSymbolicArray(symb_array);
IntegerValue symb_value = (IntegerValue) symb_array_contents.get(conc_index);
if (symb_value == null || ((Long) symb_value.getConcreteValue()).longValue() != conc_value) {
symb_value = ExpressionFactory.buildNewIntegerConstant(conc_value);
symb_array_contents.remove(conc_index);
}
return symb_value;
}
public RealValue array_load(ReferenceExpression symb_array, int conc_index, double conc_value) {
Map> symb_array_contents = getOrCreateSymbolicArray(symb_array);
RealValue symb_value = (RealValue) symb_array_contents.get(conc_index);
if (symb_value == null || ((Double) symb_value.getConcreteValue()).doubleValue() != conc_value) {
symb_value = ExpressionFactory.buildNewRealConstant(conc_value);
symb_array_contents.remove(conc_index);
}
return symb_value;
}
/**
* Initializes a reference using a concrete object
*
* @param conc_ref
* @param symb_ref
*/
public void initializeReference(Object conc_ref, ReferenceExpression symb_ref) {
if (conc_ref != null) {
if (!symb_ref.isInitialized()) {
symb_ref.initializeReference(conc_ref);
int identityHashCode = System.identityHashCode(conc_ref);
nonNullRefs.put(identityHashCode, symb_ref);
}
}
}
/**
* Constructor
*/
public SymbolicHeap() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy