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

org.evosuite.symbolic.vm.HeapVM Maven / Gradle / Ivy

/**
 * 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 static org.evosuite.dse.util.Assertions.notNull;

import java.lang.reflect.Array;
import java.lang.reflect.Field;

import org.evosuite.symbolic.expr.Expression;
import org.evosuite.symbolic.expr.IntegerConstraint;
import org.evosuite.symbolic.expr.bv.IntegerConstant;
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.instrument.ConcolicInstrumentingClassLoader;
import org.objectweb.asm.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.evosuite.dse.AbstractVM;

/**
 * Static area (static fields) and heap (instance fields)
 * 
 * FIXME: reset static state before each execution.
 * 
 * @author [email protected] (Christoph Csallner)
 */
public final class HeapVM extends AbstractVM {

	private static Logger logger = LoggerFactory.getLogger(HeapVM.class);

	private static final String ARRAY_LENGTH = "length";

	private final SymbolicEnvironment env;

	private final ConcolicInstrumentingClassLoader classLoader;

	private final PathConditionCollector pc;

	public HeapVM(SymbolicEnvironment env, PathConditionCollector pc,
			ConcolicInstrumentingClassLoader classLoader) {
		this.env = env;
		this.pc = pc;
		this.classLoader = classLoader;
	}

	/* Fields */

	/**
	 * Resolve (static or instance) field
	 * 
	 * 

* JVM Specification, Section 5.4.3.2: Field Resolution: * http://java.sun.com/ * docs/books/jvms/second_edition/html/ConstantPool.doc.html#71685 * * TODO: Resolve field once and for all, then cache it. */ public static Field resolveField(Class claz, String name) { notNull(claz, name); Field[] fields = claz.getDeclaredFields(); for (Field field : fields) if (field.getName().equals(name)) // owner declares the "name" field return field; Class[] suprs = claz.getInterfaces(); for (Class supr : suprs) { Field res = resolveField(supr, name); if (res != null) // super interface declares it return res; } Class supr = claz.getSuperclass(); if (supr != null) // super class declares it return resolveField(supr, name); return null; } /** * GetStatic mypackage/MyClass fieldName FieldType * * @param owner * name of a class or interface. * @param fieldName * name of the field to be read. The owner class or interface * itself my have declared this field. If owner is a class, then * this field may also be declared by a - super-class of the * owner class, or by a - interface implemented by (a super-class * of) the owner class. * * http://java.sun.com/docs/books/jvms/second_edition/html/ * Instructions2.doc5.html#getstatic */ @Override public void GETSTATIC(String owner, String fieldName, String desc) { /** * Prepare Class */ Class claz = env.ensurePrepared(owner); // type name given in // bytecode Field concrete_field = resolveField(claz, fieldName); // field may be // declared by // interface Class declaringClass = concrete_field.getDeclaringClass(); if (declaringClass.isInterface()) { /* * Unlikely that we ever get here. Java compiler probably computes * value of this (final) field and replaces any * "getstatic MyInterface myField" by "sipush fieldValue" or such. * Even if we get here, there should be no need to prepare this * field, as there has to be an explicit initialization, hence a * (). */ logger.debug("Do we have to prepare the static fields of an interface?"); env.ensurePrepared(declaringClass); } boolean isAccessible = concrete_field.isAccessible(); if (!isAccessible) { concrete_field.setAccessible(true); } /** * First, Get symbolic expression. If no symbolic expression exists, use * concrete value. Then, update operand stack according to type */ Type type = Type.getType(desc); try { if (type.equals(Type.INT_TYPE)) { int value = concrete_field.getInt(null); IntegerValue intExpr = (IntegerValue) env.heap.getStaticField( owner, fieldName, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.CHAR_TYPE)) { char value = concrete_field.getChar(null); IntegerValue intExpr = (IntegerValue) env.heap.getStaticField( owner, fieldName, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.SHORT_TYPE)) { short value = concrete_field.getShort(null); IntegerValue intExpr = (IntegerValue) env.heap.getStaticField( owner, fieldName, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.BOOLEAN_TYPE)) { boolean booleanValue = concrete_field.getBoolean(null); int value = booleanValue ? 1 : 0; IntegerValue intExpr = (IntegerValue) env.heap.getStaticField( owner, fieldName, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.BYTE_TYPE)) { byte value = concrete_field.getByte(null); IntegerValue intExpr = (IntegerValue) env.heap.getStaticField( owner, fieldName, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.LONG_TYPE)) { long value = concrete_field.getLong(null); IntegerValue intExpr = (IntegerValue) env.heap.getStaticField( owner, fieldName, value); env.topFrame().operandStack.pushBv64(intExpr); } else if (type.equals(Type.FLOAT_TYPE)) { float value = concrete_field.getFloat(null); RealValue fp32 = (RealValue) env.heap.getStaticField(owner, fieldName, (double) value); env.topFrame().operandStack.pushFp32(fp32); } else if (type.equals(Type.DOUBLE_TYPE)) { double value = concrete_field.getDouble(null); RealValue fp64 = (RealValue) env.heap.getStaticField(owner, fieldName, value); env.topFrame().operandStack.pushFp64(fp64); } else { Object value = concrete_field.get(null); ReferenceExpression ref = env.heap.getReference(value); env.topFrame().operandStack.pushRef(ref); } if (!isAccessible) { concrete_field.setAccessible(false); } } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } /** * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc11.html#putstatic */ @Override public void PUTSTATIC(String owner, String name, String desc) { /** * Prepare classes */ Class claz = env.ensurePrepared(owner); // type name given in // bytecode Field field = resolveField(claz, name); /* See GetStatic */ Class declaringClass = field.getDeclaringClass(); if (declaringClass.isInterface()) { logger.debug("Do we have to prepare the static fields of an interface?"); env.ensurePrepared(declaringClass); } /** * Update symbolic state (if needed) */ Operand value_operand = env.topFrame().operandStack.popOperand(); Expression symb_value = null; if (value_operand instanceof IntegerOperand) { IntegerOperand intOp = (IntegerOperand) value_operand; symb_value = intOp.getIntegerExpression(); } else if (value_operand instanceof RealOperand) { RealOperand realOp = (RealOperand) value_operand; symb_value = realOp.getRealExpression(); } else if (value_operand instanceof ReferenceOperand) { // NonNullReference are not stored in the symbolic heap fields return; } env.heap.putStaticField(owner, name, symb_value); } /** * Allocate space on the heap and push a reference ref to it onto the stack. * * For each instance field declared by class className, we add a tuple (ref, * default value) to the field's map. * * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc10.html#new */ @Override public void NEW(String className) { /** * Since this callback is invoked before the actual object creation, we * do nothing. * * We do not need to discard any elements from the operand stack since * it is given empty. * * PRE-Stack: empty * * POST-Stack: objectref (delayed) */ Class clazz = classLoader.getClassForName(className); Type objectType = Type.getType(clazz); ReferenceConstant newObject = this.env.heap.buildNewReferenceConstant(objectType); env.topFrame().operandStack.pushRef(newObject); } /** * Retrieve the value of an instance field * *

* Before actually retrieving the value, the JVM will check if the instance * is null. If the receiver instance is null, the JVM will throw a null * pointer exception. * * @see http * ://java.sun.com/docs/books/jvms/second_edition/html/Instructions2 * .doc5.html#getfield */ @Override public void GETFIELD(Object conc_receiver, String className, String fieldName, String desc) { // consume symbolic operand ReferenceExpression receiver_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_receiver, receiver_ref); Field field = resolveField(classLoader.getClassForName(className), fieldName); env.ensurePrepared(field.getDeclaringClass()); boolean isAccessible = field.isAccessible(); if (!isAccessible) { field.setAccessible(true); } /* * Schedule reference field type to be asserted -- before null check, as * null check will create a new node in path constraint */ /* null-check */ if (nullReferenceViolation(receiver_ref, conc_receiver)) { return; } ReferenceExpression symb_receiver = receiver_ref; Type type = Type.getType(desc); try { if (type.equals(Type.INT_TYPE)) { int value = field.getInt(conc_receiver); IntegerValue intExpr = (IntegerValue) env.heap.getField( className, fieldName, conc_receiver, symb_receiver, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.LONG_TYPE)) { long value = field.getLong(conc_receiver); IntegerValue intExpr = (IntegerValue) env.heap.getField( className, fieldName, conc_receiver, symb_receiver, value); env.topFrame().operandStack.pushBv64(intExpr); } else if (type.equals(Type.FLOAT_TYPE)) { float value = field.getFloat(conc_receiver); RealValue fp32 = (RealValue) env.heap .getField(className, fieldName, conc_receiver, symb_receiver, (double) value); env.topFrame().operandStack.pushFp32(fp32); } else if (type.equals(Type.DOUBLE_TYPE)) { double value = field.getDouble(conc_receiver); RealValue fp64 = (RealValue) env.heap.getField(className, fieldName, conc_receiver, symb_receiver, value); env.topFrame().operandStack.pushFp64(fp64); } else if (type.equals(Type.CHAR_TYPE)) { char value = field.getChar(conc_receiver); IntegerValue intExpr = (IntegerValue) env.heap.getField( className, fieldName, conc_receiver, symb_receiver, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.SHORT_TYPE)) { short value = field.getShort(conc_receiver); IntegerValue intExpr = (IntegerValue) env.heap.getField( className, fieldName, conc_receiver, symb_receiver, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.BOOLEAN_TYPE)) { boolean booleanValue = field.getBoolean(conc_receiver); int value = booleanValue ? 1 : 0; IntegerValue intExpr = (IntegerValue) env.heap.getField( className, fieldName, conc_receiver, symb_receiver, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else if (type.equals(Type.BYTE_TYPE)) { byte value = field.getByte(conc_receiver); IntegerValue intExpr = (IntegerValue) env.heap.getField( className, fieldName, conc_receiver, symb_receiver, (long) value); env.topFrame().operandStack.pushBv32(intExpr); } else { Object value = field.get(conc_receiver); ReferenceExpression ref = env.heap.getReference(value); env.topFrame().operandStack.pushRef(ref); } if (!isAccessible) { field.setAccessible(false); } } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } /** * Store a value in an instance field. * * Before actually retrieving the value, the JVM will check if the instance * is null. If the receiver instance is null, the JVM will throw a null * pointer exception. */ @Override public void PUTFIELD(Object conc_receiver, String className, String fieldName, String desc) { /** * Pop symbolic heap */ Operand value_operand = env.topFrame().operandStack.popOperand(); ReferenceExpression receiver_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_receiver, receiver_ref); /** * Prepare classes */ Field field = resolveField(classLoader.getClassForName(className), fieldName); env.ensurePrepared(field.getDeclaringClass()); /* null-check */ if (nullReferenceViolation(receiver_ref, conc_receiver)) { return; } ReferenceExpression symb_receiver = (ReferenceExpression) receiver_ref; /** * Compute new symbolic state */ Expression symb_value = null; if (value_operand instanceof IntegerOperand) { IntegerOperand intOp = (IntegerOperand) value_operand; symb_value = intOp.getIntegerExpression(); } else if (value_operand instanceof RealOperand) { RealOperand realOp = (RealOperand) value_operand; symb_value = realOp.getRealExpression(); } else if (value_operand instanceof ReferenceOperand) { // NonNullReference are not stored in the symbolic heap fields return; } env.heap.putField(className, fieldName, conc_receiver, symb_receiver, symb_value); } /* Arrays */ /** * Create a (one-dimensional) array of primitive componenet type, e.g., new * int[3] * * Allocate space on the heap and push a reference ref to it onto the stack. * * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc10.html#newarray */ @Override public void NEWARRAY(int conc_array_length, Class componentType) { /** * Since this callback is invoked before the actual array creation, we * can only add negative index constraints. * * PRE: int (length) * * POST: arrayref (delayed) */ // discard symbolic arguments IntegerValue symb_array_length = env.topFrame().operandStack.popBv32(); /* negative index */ if (negativeArrayLengthViolation(conc_array_length, symb_array_length)) return; // create array class int[] lenghts = new int[] { 0 }; Class array_class = Array.newInstance(componentType, lenghts) .getClass(); Type arrayType = Type.getType(array_class); ReferenceConstant symb_array_ref = this.env.heap.buildNewReferenceConstant(arrayType); env.heap.putField("", ARRAY_LENGTH, null, symb_array_ref, symb_array_length); env.topFrame().operandStack.pushRef(symb_array_ref); } /** * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc * .html#anewarray */ @Override public void ANEWARRAY(int conc_array_length, String componentTypeName) { /** * Since this callback is invoked before the actual array creation, we * can only add negative index constraints. * * PRE: int (length) * * POST: arrayref (delayed) */ // discard symbolic arguments IntegerValue symb_array_length = env.topFrame().operandStack.popBv32(); /* negative index */ if (negativeArrayLengthViolation(conc_array_length, symb_array_length)) return; // create array class Type componentType = Type.getType(componentTypeName.replace('/', '.')); ClasscomponentClass = classLoader.getClassForType(componentType); int[] lenghts = new int[] { 0 }; Class array_class = Array.newInstance(componentClass, lenghts) .getClass(); Type arrayType = Type.getType(array_class); ReferenceConstant symb_array_ref = env.heap.buildNewReferenceConstant(arrayType); env.heap.putField("", ARRAY_LENGTH, null, symb_array_ref, symb_array_length); env.topFrame().operandStack.pushRef(symb_array_ref); } /** * MULTIANEWARRAY * *

	 * boolean[] b1 = new boolean[1]; // NEWARRAY T_BOOLEAN
	 * Boolean[] B1 = new Boolean[1]; // ANEWARRAY java/lang/Boolean
	 * boolean[][] b2 = new boolean[1][2]; // MULTIANEWARRAY [[Z 2
	 * Boolean[][] B2 = new Boolean[1][2]; // MULTIANEWARRAY [[Ljava/lang/Boolean; 2
	 * 
*/ @Override public void MULTIANEWARRAY(String arrayTypeDesc, int nrDimensions) { /** * Since this callback is invoked before the actual array creation, we * can only add negative index constraints. * * PRE: int (dimensions) | ... | int (size2) | int (size1) * * POST: arrayref (delayed) */ // push negartive length constraints for (int i = 0; i < nrDimensions; i++) { IntegerValue symb_length = env.topFrame().operandStack.popBv32(); int conc_length = ((Long) symb_length.getConcreteValue()) .intValue(); if (negativeArrayLengthViolation(conc_length, symb_length)) { return; } } Type multiArrayType = Type.getType(arrayTypeDesc); // push delayed object ReferenceConstant newMultiArray = this.env.heap .buildNewReferenceConstant(multiArrayType); // @FIXME env.topFrame().operandStack.pushRef(newMultiArray); } @Override public void ARRAYLENGTH(Object conc_array) { /* get symbolic arguments */ ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } int conc_array_length = Array.getLength(conc_array); ReferenceExpression symb_array_ref = (ReferenceExpression) array_ref; IntegerValue symb_array_length = (IntegerValue) env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array_ref, conc_array_length); env.topFrame().operandStack.pushBv32(symb_array_length); } /** * Load an int value from an array and push it on the stack * * ..., arrayref, index ==> ..., value * * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc6.html#iaload */ @Override public void IALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = (ReferenceExpression) array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; int bv32 = Array.getInt(conc_array, conc_index); IntegerValue c = env.heap.array_load(symb_array, conc_index, (long) bv32); env.topFrame().operandStack.pushBv32(c); } @Override public void LALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = (ReferenceExpression) array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; long bv64 = Array.getLong(conc_array, conc_index); IntegerValue c = env.heap.array_load(symb_array, conc_index, (long) bv64); env.topFrame().operandStack.pushBv64(c); } @Override public void FALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = (ReferenceExpression) array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; float fp32 = Array.getFloat(conc_array, conc_index); RealValue c = env.heap .array_load(symb_array, conc_index, (double) fp32); env.topFrame().operandStack.pushFp32(c); } /** * Load double from array * * ..., arrayref, index ==> ..., value * * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc3.html#daload */ @Override public void DALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = (ReferenceExpression) array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; double fp64 = Array.getDouble(conc_array, conc_index); RealValue c = env.heap .array_load(symb_array, conc_index, (double) fp64); env.topFrame().operandStack.pushFp64(c); } @Override public void AALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = (ReferenceExpression) array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; Object conc_value = Array.get(conc_array, conc_index); ReferenceExpression symb_value; if (conc_value == null) { symb_value = ExpressionFactory.buildNewNullExpression(); } else { symb_value = env.heap.getReference(conc_value); } env.topFrame().operandStack.pushRef(symb_value); } private boolean indexTooBigViolation(int conc_index, IntegerValue symb_index, int conc_array_length, IntegerValue symb_array_length) { IntegerConstraint indexTooBigConstraint; if (conc_index >= conc_array_length) { indexTooBigConstraint = ConstraintFactory.gte(symb_index, symb_array_length); if (indexTooBigConstraint.getLeftOperand() .containsSymbolicVariable() || indexTooBigConstraint.getRightOperand() .containsSymbolicVariable()) this.pc.appendSupportingConstraint(indexTooBigConstraint); return true; } else { indexTooBigConstraint = ConstraintFactory.lt(symb_index, symb_array_length); if (indexTooBigConstraint.getLeftOperand() .containsSymbolicVariable() || indexTooBigConstraint.getRightOperand() .containsSymbolicVariable()) this.pc.appendSupportingConstraint(indexTooBigConstraint); return false; } } private boolean nullReferenceViolation(ReferenceExpression symb_ref, Object conc_ref) { // TODO: Add constraint to path condition if (conc_ref == null) return true; else return false; } private boolean negativeIndexViolation(int conc_index, IntegerValue symb_index) { IntegerConstraint negative_index_constraint; if (conc_index < 0) { negative_index_constraint = ConstraintFactory.lt(symb_index, ExpressionFactory.ICONST_0); if (negative_index_constraint.getLeftOperand() .containsSymbolicVariable() || negative_index_constraint.getRightOperand() .containsSymbolicVariable()) pc.appendSupportingConstraint(negative_index_constraint); return true; } else { negative_index_constraint = ConstraintFactory.gte(symb_index, ExpressionFactory.ICONST_0); if (negative_index_constraint.getLeftOperand() .containsSymbolicVariable() || negative_index_constraint.getRightOperand() .containsSymbolicVariable()) pc.appendSupportingConstraint(negative_index_constraint); return false; } } private boolean negativeArrayLengthViolation(int conc_array_length, IntegerValue array_length_index) { IntegerConstraint negative_array_length_constraint; if (conc_array_length < 0) { negative_array_length_constraint = ConstraintFactory.lt( array_length_index, ExpressionFactory.ICONST_0); if (negative_array_length_constraint.getLeftOperand() .containsSymbolicVariable() || negative_array_length_constraint.getRightOperand() .containsSymbolicVariable()) pc.appendSupportingConstraint(negative_array_length_constraint); return true; } else { negative_array_length_constraint = ConstraintFactory.gte( array_length_index, ExpressionFactory.ICONST_0); if (negative_array_length_constraint.getLeftOperand() .containsSymbolicVariable() || negative_array_length_constraint.getRightOperand() .containsSymbolicVariable()) pc.appendSupportingConstraint(negative_array_length_constraint); return false; } } /** * retrieve byte/boolean from array */ @Override public void BALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; Object object = Array.get(conc_array, conc_index); int intValue; if (object instanceof Boolean) { boolean booleanValue = ((Boolean) object).booleanValue(); intValue = booleanValue ? 1 : 0; } else { assert object instanceof Byte; intValue = ((Byte) object).shortValue(); } IntegerValue c = env.heap.array_load(symb_array, conc_index, (long) intValue); env.topFrame().operandStack.pushBv32(c); } @Override public void CALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; char bv32 = Array.getChar(conc_array, conc_index); IntegerValue c = env.heap.array_load(symb_array, conc_index, (long) bv32); env.topFrame().operandStack.pushBv32(c); } @Override public void SALOAD(Object conc_array, int conc_index) { // pop symbolic arguments IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; short conc_value = Array.getShort(conc_array, conc_index); IntegerValue e = env.heap.array_load(symb_array, conc_index, (long) conc_value); env.topFrame().operandStack.pushBv32(e); } /** * Store the top operand stack value into an array * * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc6.html#iastore */ @Override public void IASTORE(Object conc_array, int conc_index) { // pop arguments IntegerValue symb_value = env.topFrame().operandStack.popBv32(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array =array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; env.heap.array_store(conc_array, symb_array, conc_index, symb_value); } @Override public void LASTORE(Object conc_array, int conc_index) { // get symbolic arguments IntegerValue symb_value = env.topFrame().operandStack.popBv64(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; env.heap.array_store(conc_array, symb_array, conc_index, symb_value); } @Override public void FASTORE(Object conc_array, int conc_index) { // get symbolic arguments RealValue symb_value = env.topFrame().operandStack.popFp32(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; env.heap.array_store(conc_array, symb_array, conc_index, symb_value); } @Override public void DASTORE(Object conc_array, int conc_index) { // get symbolic arguments RealValue symb_value = env.topFrame().operandStack.popFp64(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; env.heap.array_store(conc_array, symb_array, conc_index, symb_value); } /** * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc * .html#aastore */ @Override public void AASTORE(Object conc_array, int conc_index) { // pop arguments @SuppressWarnings("unused") ReferenceExpression value_ref = env.topFrame().operandStack.popRef(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; // NonNullReference are not stored in the symbolic heap fields return; } @Override public void BASTORE(Object conc_array, int conc_index) { // pop arguments IntegerValue symb_value = env.topFrame().operandStack.popBv32(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; env.heap.array_store(conc_array, symb_array, conc_index, symb_value); } @Override public void CASTORE(Object conc_array, int conc_index) { // pop arguments IntegerValue symb_value = env.topFrame().operandStack.popBv32(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; env.heap.array_store(conc_array, symb_array, conc_index, symb_value); } @Override public void SASTORE(Object conc_array, int conc_index) { // get symbolic arguments IntegerValue symb_value = env.topFrame().operandStack.popBv32(); IntegerValue symb_index = env.topFrame().operandStack.popBv32(); ReferenceExpression array_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_array, array_ref); /* null-check */ if (nullReferenceViolation(array_ref, conc_array)) { return; } /* negative index */ if (negativeIndexViolation(conc_index, symb_index)) { return; } /* out of bound index */ ReferenceExpression symb_array = array_ref; int conc_array_length = Array.getLength(conc_array); IntegerValue symb_array_length = env.heap.getField("", ARRAY_LENGTH, conc_array, symb_array, conc_array_length); if (indexTooBigViolation(conc_index, symb_index, conc_array_length, symb_array_length)) return; env.heap.array_store(conc_array, symb_array, conc_index, symb_value); } /** * Explicit type cast: * *
	 * RefTypeX x = (RefTypeX) ref;
	 * 
* * null is treated as (can be cast to) any reference type. This is * consistent with the null type being a subtype of every reference type. * Note the different treatment in {@link #INSTANCEOF}. * * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc2.html#checkcast */ @Override public void CHECKCAST(Object conc_ref, String typeName) { ReferenceExpression symb_ref = env.topFrame().operandStack.peekRef(); env.heap.initializeReference(conc_ref, symb_ref); } /** * Dynamic type check: * *
	 * (variable instanceof TypeName)
	 * 
* * null is not treated as (is not an instance of) any reference type. This * requires non-standard treatment of null. Note the different treatment in * {@link #CHECKCAST}. * *

* If the jvm has not loaded the class/interface named TypeName before, then * we load it. TODO: Is this a problem? * * http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2. * doc6.html#instanceof */ @Override public void INSTANCEOF(Object conc_ref, String typeName) { /* pop symbolic arguments */ ReferenceExpression symb_ref = env.topFrame().operandStack.popRef(); /* check reference initialization */ env.heap.initializeReference(conc_ref, symb_ref); Type type = Type.getType(typeName); Class myClazz = classLoader.getClassForType(type); boolean instanceOf = myClazz.isInstance(conc_ref); IntegerConstant ret; if (instanceOf) { ret = ExpressionFactory.ICONST_1; } else { ret = ExpressionFactory.ICONST_0; } /* push symbolic arguments */ env.topFrame().operandStack.pushBv32(ret); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy