Skip to content

Commit

Permalink
added a domain that computes type information related to uninitialize…
Browse files Browse the repository at this point in the history
…d values

Signed-off-by: Michael Eichberg <mail@michael-eichberg.de>
  • Loading branch information
Delors committed Dec 12, 2017
1 parent 537681b commit 56368ee
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 16 deletions.
5 changes: 3 additions & 2 deletions OPAL/ai/src/main/scala/org/opalj/ai/AI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,12 @@ abstract class AI[D <: Domain]( final val IdentifyDeadVariables: Boolean = true)
val thisType = method.classFile.thisType
val thisValue =
if (method.isConstructor &&
(method.classFile.thisType ne ObjectType.Object))
(method.classFile.thisType ne ObjectType.Object)) {
// ... we have an uninitialized this!
domain.NewObject(origin(localVariableIndex), thisType)
else
} else {
domain.NonNullObjectValue(origin(localVariableIndex), thisType)
}
locals.set(localVariableIndex, thisValue)
localVariableIndex += 1 /*==thisType.computationalType.operandSize*/
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ import org.opalj.br.instructions.Instruction
* Provides the possibility to further update the memory layout (registers and operands)
* after the execution of an instruction, but before any potential join is performed.
*
* Using this domain is only safe if the (partial-)domains that use this functionality
* never interfere with each other.
*
* @note If this domain is mixed in then the domain cannot be used to simultaneously analyze
* multiple different methods at the same time.
*
Expand All @@ -56,8 +59,8 @@ trait PostEvaluationMemoryManagement extends CoreDomainFunctionality {

assert(oldValue ne null)
assert((newValueAfterEvaluation ne null) || (newValueAfterException ne null))
assert(oldValue ne newValueAfterEvaluation, "it doesn't make sense to update a value with itself")
assert(oldValue ne newValueAfterException, "it doesn't make sense to update a value with itself")
assert(oldValue ne newValueAfterEvaluation, "useless self update")
assert(oldValue ne newValueAfterException, "useless self update")

this.oldValue = oldValue
this.newValueAfterEvaluation = newValueAfterEvaluation
Expand Down Expand Up @@ -97,11 +100,12 @@ trait PostEvaluationMemoryManagement extends CoreDomainFunctionality {
pc, instruction, oldOperands, oldLocals,
targetPC, isExceptionalControlFlow, operands1, locals1
)
} else
} else {
super.afterEvaluation(
pc, instruction, oldOperands, oldLocals,
targetPC, isExceptionalControlFlow, newOperands, newLocals
)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.opalj.ai.domain.l0
package org.opalj
package ai
package domain
package l0

import org.opalj.ai.TheClassHierarchy
import org.opalj.ai.domain.ThrowAllPotentialExceptionsConfiguration
import org.opalj.ai.domain.IgnoreSynchronization
import org.opalj.ai.domain.TheMethod
import org.opalj.br.Method
import org.opalj.br.ClassHierarchy
import org.opalj.br.analyses.SomeProject
Expand All @@ -43,10 +42,20 @@ import org.opalj.br.analyses.SomeProject
class TypeCheckingDomain(
val classHierarchy: ClassHierarchy,
val method: Method
) extends TypeLevelDomain
) extends Domain
with DefaultDomainValueBinding
with DefaultTypeLevelIntegerValues
with DefaultTypeLevelLongValues
with TypeLevelLongValuesShiftOperators
with TypeLevelPrimitiveValuesConversions
with DefaultTypeLevelFloatValues
with DefaultTypeLevelDoubleValues
with TypeLevelFieldAccessInstructions
with TypeLevelInvokeInstructions
with ThrowAllPotentialExceptionsConfiguration
with IgnoreSynchronization
with DefaultTypeLevelHandlingOfMethodResults
with TypeCheckingReferenceValues // we override the handling for invokespecial...
with TheClassHierarchy
with TheMethod {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ package domain
package l0

import scala.reflect.ClassTag

import org.opalj.collection.immutable.UIDSet
import org.opalj.br.ArrayType
import org.opalj.br.ObjectType
import org.opalj.br.MethodDescriptor

/**
* Default implementation for handling reference values in such a way that we can compute
Expand All @@ -45,7 +45,9 @@ import org.opalj.br.ObjectType
*/
trait TypeCheckingReferenceValues
extends DefaultTypeLevelReferenceValues
with DefaultExceptionsFactory {
with DefaultExceptionsFactory
with MethodCallsDomain
with PostEvaluationMemoryManagement {
domain: IntegerValuesDomain with TypedValuesFactory with Configuration with TheClassHierarchy

type AReferenceValue = ReferenceValue
Expand All @@ -72,7 +74,6 @@ trait TypeCheckingReferenceValues

// WIDENING OPERATION
override protected def doJoin(pc: PC, other: DomainValue): Update[DomainValue] = {
val thisUpperTypeBound = this.theUpperTypeBound
other match {
case _: UninitializedObjectValue MetaInformationUpdateIllegalValue
case that super.doJoin(pc, that)
Expand Down Expand Up @@ -118,6 +119,25 @@ trait TypeCheckingReferenceValues
target.NewObject(origin, theUpperTypeBound)
}

override def toString: String = s"${theType.toJava}(uninitialized;origin=$pc)"
}

abstract override def invokespecial(
pc: PC,
declaringClass: ObjectType,
isInterface: Boolean,
name: String,
methodDescriptor: MethodDescriptor,
operands: Operands
): MethodCallResult = {
if (name == "<init>") {
val receiver = operands.last
// the value is now initialized and we have to update the stack/locals
val UninitializedObjectValue(theType, _) = receiver
val initializedObjectValue = new InitializedObjectValue(theType)
updateAfterExecution(receiver, initializedObjectValue, TheIllegalValue)
}
super.invokespecial(pc, declaringClass, isInterface, name, methodDescriptor, operands)
}

// -----------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ package instructions
*/
abstract class ArrayAccessInstruction
extends Instruction
with ConstantLengthInstruction
with NoLabels {
with ConstantLengthInstruction
with NoLabels {

final def length: Int = 1

Expand Down

0 comments on commit 56368ee

Please sign in to comment.