Skip to content

Support of UTypeStreams and casts in JcInterpreter #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 57 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
21d8a27
Draft
sergeypospelov Jun 9, 2023
8db7222
Draft
sergeypospelov Jul 4, 2023
6829379
Draft
sergeypospelov Jul 4, 2023
3d2af70
Uncomment disables
sergeypospelov Jul 4, 2023
c8c470a
Allowed setting final fields using reflection
Damtev Jul 4, 2023
3f1d6a0
WIP disabling irrelevant failing tests
Damtev Jul 4, 2023
176fc45
Revert "Allowed setting final fields using reflection"
sergeypospelov Jul 5, 2023
f2f4cc8
Add: revert static fields, update JacoDB version
sergeypospelov Jul 5, 2023
d7f6325
WIP disabling irrelevant tests
Damtev Jul 5, 2023
d089f43
Returned opening modules
Damtev Jul 5, 2023
6cf264b
WIP disabling irrelevant failing tests
Damtev Jul 5, 2023
572e9b4
Disabled testing constructors
Damtev Jul 5, 2023
5045cb7
WIP disabling irrelevant failing tests
Damtev Jul 5, 2023
67fca0b
Fix: jacodb
sergeypospelov Jul 5, 2023
8731490
Fix: tests
sergeypospelov Jul 5, 2023
65396ba
WIP enabling tests
Damtev Jul 5, 2023
71235ef
Fixed failing tests for sample language
Damtev Jul 6, 2023
ae2576e
Disabled test for casting float to int
Damtev Jul 6, 2023
3523c4f
Fixed searching of subclasses of primitives
Damtev Jul 6, 2023
de4c31c
WIP disabling irrelevant failing tests
Damtev Jul 6, 2023
c14d7c4
WIP disabling irrelevant failing tests
Damtev Jul 6, 2023
cb79dee
Disabled tests with instanceof
Damtev Jul 6, 2023
cef3053
Fix: some tests
sergeypospelov Jul 6, 2023
6dda70f
Opened more modules
Damtev Jul 7, 2023
cce6534
Opened one more module
Damtev Jul 7, 2023
8b6b0b0
Disabled count of branches for tests with not null annotations
Damtev Jul 7, 2023
236fca2
Fix: `UNullRef` readings and `UIsExpr`s for nulls
sergeypospelov Jul 7, 2023
2e9e63d
WIP disabling irrelevant failing tests
Damtev Jul 7, 2023
f2c8e28
Fix: some tests
sergeypospelov Jul 7, 2023
2f8ae07
Fix: cycles test
sergeypospelov Jul 7, 2023
bb6e8f9
WIP disabling irrelevant failing tests
Damtev Jul 7, 2023
aacfee6
Fix: some tests
sergeypospelov Jul 7, 2023
7a77b8b
Used a lib to export all modules
Damtev Jul 7, 2023
9318cce
Disabled some more tests with assumptions
Damtev Jul 7, 2023
4e1a04a
Fix: disable irrelevant tests
sergeypospelov Jul 7, 2023
b3b774f
Fixed compilation error
Damtev Jul 10, 2023
8aa3e63
Rewritten matcher
Damtev Jul 10, 2023
ebfd0c5
Fix: disabled and enabled tests, update jacodb version
sergeypospelov Jul 10, 2023
ee1d1fd
Disable irrelevant tests
sergeypospelov Jul 10, 2023
89c8f3e
Move addresses constants to Expressions.kt
sergeypospelov Jul 10, 2023
af6bc32
Fix CE and add a comment
sergeypospelov Jul 10, 2023
39e0d8d
Add comments and a few tests
sergeypospelov Jul 10, 2023
3f68a8e
Rename to unify with other methods
sergeypospelov Jul 10, 2023
c77abc0
Add comments
sergeypospelov Jul 10, 2023
221ef99
Add comments
sergeypospelov Jul 10, 2023
dac561d
Remove mavenLocal
sergeypospelov Jul 10, 2023
d04647b
Add comments
sergeypospelov Jul 10, 2023
40d8d9e
Fix imports
sergeypospelov Jul 10, 2023
8d18331
Fix test
sergeypospelov Jul 10, 2023
5267ebe
Review fixes and change `UTypeStream` signature
sergeypospelov Jul 11, 2023
a7bd3cf
Introduce `UReadOnlyTypedMemory` and refactor `UTypeModel`
sergeypospelov Jul 11, 2023
bc5436c
Enabled some more tests
Damtev Jul 11, 2023
cf0bc7f
Fix type solving procedure
sergeypospelov Jul 11, 2023
7209949
Fix review comments
sergeypospelov Jul 12, 2023
69c0fcd
Fix comments
sergeypospelov Jul 12, 2023
6da10bb
Fix comments again
sergeypospelov Jul 12, 2023
b53cccf
Refactoring empty type stream
Damtev Jul 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ object Versions {
const val ksmt = "0.5.3"
const val collections = "0.3.5"
const val coroutines = "1.6.4"
const val jcdb = "1.0.0"
const val jcdb = "1.1.3"
const val mockk = "1.13.4"
const val junitParams = "5.9.3"

Expand Down
5 changes: 3 additions & 2 deletions usvm-core/src/main/kotlin/org/usvm/Context.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.usvm.memory.UInputArrayRegion
import org.usvm.memory.UInputFieldRegion
import org.usvm.memory.splitUHeapRef
import org.usvm.solver.USolverBase
import org.usvm.types.UTypeSystem

@Suppress("LeakingThis")
open class UContext(
Expand Down Expand Up @@ -91,8 +92,8 @@ open class UContext(
lhs is UConcreteHeapRef && rhs is UConcreteHeapRef -> mkBool(lhs == rhs)
// unfolding
else -> {
val (concreteRefsLhs, symbolicRefLhs) = splitUHeapRef(lhs)
val (concreteRefsRhs, symbolicRefRhs) = splitUHeapRef(rhs)
val (concreteRefsLhs, symbolicRefLhs) = splitUHeapRef(lhs, ignoreNullRefs = false)
val (concreteRefsRhs, symbolicRefRhs) = splitUHeapRef(rhs, ignoreNullRefs = false)

val concreteRefLhsToGuard = concreteRefsLhs.associate { it.expr.address to it.guard }

Expand Down
30 changes: 28 additions & 2 deletions usvm-core/src/main/kotlin/org/usvm/Expressions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,28 @@ class UNullRef internal constructor(
}
}

// We split all addresses into three parts:
// * input values: [Int.MIN_VALUE..0),
// * null value: [0]
// * allocated values: (0..[Int.MAX_VALUE]

/**
* A constant corresponding to `null`.
*/
const val NULL_ADDRESS = 0

/**
* A constant corresponding to the first input address in any decoded model.
* Input addresses takes this semi-interval: [[Int.MIN_VALUE]..0)
*/
const val INITIAL_INPUT_ADDRESS = NULL_ADDRESS - 1
/**
* A constant corresponding to the first allocated address in any symbolic memory.
* Input addresses takes this semi-interval: (0..[Int.MAX_VALUE])
*/
const val INITIAL_CONCRETE_ADDRESS = NULL_ADDRESS + 1


//endregion

//region LValues
Expand Down Expand Up @@ -342,6 +364,10 @@ class UIndexedMethodReturnValue<Method, Sort : USort> internal constructor(

//region Subtyping Expressions

/**
* Means **either** [ref] is [UNullRef] **or** [ref] !is [UNullRef] and [ref] <: [type]. Thus, the actual type
* inheritance is checked only on non-null refs.
*/
class UIsExpr<Type> internal constructor(
ctx: UContext,
val ref: UHeapRef,
Expand All @@ -358,7 +384,7 @@ class UIsExpr<Type> internal constructor(


override fun print(printer: ExpressionPrinter) {
TODO("Not yet implemented")
printer.append("($ref instance of $type)")
}

override fun internEquals(other: Any): Boolean = structurallyEqual(other, { ref }, { type })
Expand All @@ -372,4 +398,4 @@ class UIsExpr<Type> internal constructor(
val UBoolExpr.isFalse get() = this == ctx.falseExpr
val UBoolExpr.isTrue get() = this == ctx.trueExpr

//endregion
//endregion
6 changes: 2 additions & 4 deletions usvm-core/src/main/kotlin/org/usvm/State.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ abstract class UState<Type, Field, Method, Statement>(
open var models: List<UModelBase<Field, Type>>,
open var path: PersistentList<Statement>
) {
open val ctx: UContext = ctx

/**
* Deterministic state id.
* TODO: Can be replaced with overridden hashCode
Expand Down Expand Up @@ -74,7 +72,7 @@ private fun <T : UState<Type, Field, *, *>, Type, Field> forkIfSat(
return null
}

val solver = state.ctx.solver<Field, Type, Any?>()
val solver = satisfiedCondition.uctx.solver<Field, Type, Any?>()
val satResult = solver.check(pathConstraints, useSoftConstraints = true)

return when (satResult) {
Expand Down Expand Up @@ -133,7 +131,7 @@ fun <T : UState<Type, Field, *, *>, Type, Field> fork(
holdsInModel.isTrue
}

val notCondition = state.ctx.mkNot(condition)
val notCondition = condition.uctx.mkNot(condition)
val (posState, negState) = when {

trueModels.isNotEmpty() && falseModels.isNotEmpty() -> {
Expand Down
2 changes: 1 addition & 1 deletion usvm-core/src/main/kotlin/org/usvm/StepScope.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class StepScope<T : UState<Type, Field, *, *>, Type, Field>(
* Forks on a [condition], performing [blockOnTrueState] on a state satisfying [condition] and
* [blockOnFalseState] on a state satisfying [condition].not().
*
* If the [condition], sets underlying state to `null`.
* If the [condition] is unsatisfiable, sets underlying state to `null`.
*
* @return `null` if the [condition] is unsatisfiable.
*/
Expand Down
19 changes: 0 additions & 19 deletions usvm-core/src/main/kotlin/org/usvm/TypeSystem.kt

This file was deleted.

1 change: 1 addition & 0 deletions usvm-core/src/main/kotlin/org/usvm/UComponents.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.usvm

import org.usvm.solver.USolverBase
import org.usvm.types.UTypeSystem

/**
* Provides core USVM components tuned for specific language.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ class UEqualityConstraints private constructor(
equalReferences.subscribe(::rename)
}

var isContradiction = false
var isContradicting = false
private set

private fun contradiction() {
isContradiction = true
isContradicting = true
equalReferences.clear()
mutableDistinctReferences.clear()
mutableReferenceDisequalities.clear()
Expand Down Expand Up @@ -89,8 +89,8 @@ class UEqualityConstraints private constructor(
/**
* Adds an assertion that [ref1] is always equal to [ref2].
*/
fun addReferenceEquality(ref1: UHeapRef, ref2: UHeapRef) {
if (isContradiction) {
fun makeEqual(ref1: UHeapRef, ref2: UHeapRef) {
if (isContradicting) {
return
}

Expand Down Expand Up @@ -125,7 +125,7 @@ class UEqualityConstraints private constructor(
mutableReferenceDisequalities.remove(from)
fromDiseqs.forEach {
mutableReferenceDisequalities[it]?.remove(from)
addReferenceDisequality(to, it)
makeNonEqual(to, it)
}
}

Expand All @@ -142,7 +142,7 @@ class UEqualityConstraints private constructor(
}
} else if (containsNullableDisequality(from, to)) {
// If x === y, nullable disequality can hold only if both references are null
addReferenceEquality(to, nullRepr)
makeEqual(to, nullRepr)
} else {
val removedFrom = mutableNullableDisequalities.remove(from)
removedFrom?.forEach {
Expand Down Expand Up @@ -210,8 +210,8 @@ class UEqualityConstraints private constructor(
/**
* Adds an assertion that [ref1] is never equal to [ref2].
*/
fun addReferenceDisequality(ref1: UHeapRef, ref2: UHeapRef) {
if (isContradiction) {
fun makeNonEqual(ref1: UHeapRef, ref2: UHeapRef) {
if (isContradicting) {
return
}

Expand All @@ -233,7 +233,7 @@ class UEqualityConstraints private constructor(
* Adds an assertion that [ref1] is never equal to [ref2] or both are null.
*/
fun makeNonEqualOrBothNull(ref1: UHeapRef, ref2: UHeapRef) {
if (isContradiction) {
if (isContradicting) {
return
}

Expand All @@ -242,7 +242,7 @@ class UEqualityConstraints private constructor(

if (repr1 == repr2) {
// In this case, (repr1 != repr2) || (repr1 == null && repr2 == null) is equivalent to (repr1 == null).
addReferenceEquality(repr1, ctx.nullRef)
makeEqual(repr1, ctx.nullRef)
return
}

Expand Down Expand Up @@ -284,9 +284,9 @@ class UEqualityConstraints private constructor(
* Note that current subscribers get unsubscribed!
*/
fun clone(): UEqualityConstraints {
if (isContradiction) {
if (isContradicting) {
val result = UEqualityConstraints(ctx, DisjointSets(), mutableSetOf(), mutableMapOf(), mutableMapOf())
result.isContradiction = true
result.isContradicting = true
return result
}

Expand Down
15 changes: 10 additions & 5 deletions usvm-core/src/main/kotlin/org/usvm/constraints/PathConstraints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ open class UPathConstraints<Type> private constructor(
constructor(ctx: UContext) : this(ctx, persistentSetOf())

open val isFalse: Boolean
get() = equalityConstraints.isContradiction ||
typeConstraints.isContradiction ||
get() = equalityConstraints.isContradicting ||
typeConstraints.isContradicting ||
logicalConstraints.singleOrNull() is UFalse

@Suppress("UNCHECKED_CAST")
Expand All @@ -54,9 +54,9 @@ open class UPathConstraints<Type> private constructor(
constraint == trueExpr || constraint in logicalConstraints -> {}

constraint is UEqExpr<*> && isSymbolicHeapRef(constraint.lhs) && isSymbolicHeapRef(constraint.rhs) ->
equalityConstraints.addReferenceEquality(constraint.lhs as UHeapRef, constraint.rhs as UHeapRef)
equalityConstraints.makeEqual(constraint.lhs as UHeapRef, constraint.rhs as UHeapRef)

constraint is UIsExpr<*> -> typeConstraints.cast(constraint.ref, constraint.type as Type)
constraint is UIsExpr<*> -> typeConstraints.addSupertype(constraint.ref, constraint.type as Type)

constraint is UAndExpr -> constraint.args.forEach(::plusAssign)

Expand All @@ -67,12 +67,17 @@ open class UPathConstraints<Type> private constructor(
isSymbolicHeapRef(notConstraint.lhs) &&
isSymbolicHeapRef(notConstraint.rhs) -> {
require(notConstraint.rhs.sort == addressSort)
equalityConstraints.addReferenceDisequality(
equalityConstraints.makeNonEqual(
notConstraint.lhs as UHeapRef,
notConstraint.rhs as UHeapRef
)
}

notConstraint is UIsExpr<*> -> typeConstraints.excludeSupertype(
notConstraint.ref,
notConstraint.type as Type
)

notConstraint in logicalConstraints -> contradiction(ctx)

notConstraint is UOrExpr -> notConstraint.args.forEach { plusAssign(ctx.mkNot(it)) }
Expand Down
Loading