Skip to content
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

Basic USVM TS type system with type coercion #215

Open
wants to merge 44 commits into
base: main
Choose a base branch
from

Conversation

zishkaz
Copy link
Collaborator

@zishkaz zishkaz commented Sep 30, 2024

No description provided.

@zishkaz zishkaz requested a review from CaelmBleidd September 30, 2024 10:06
@zishkaz zishkaz self-assigned this Sep 30, 2024
@zishkaz zishkaz marked this pull request as draft September 30, 2024 11:40
Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detekt found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@zishkaz
Copy link
Collaborator Author

zishkaz commented Oct 3, 2024

This PR indirectly introduces a bug

@zishkaz zishkaz marked this pull request as ready for review October 3, 2024 08:24
.github/workflows/build-and-run-tests.yml Outdated Show resolved Hide resolved
usvm-core/src/main/kotlin/org/usvm/StateForker.kt Outdated Show resolved Hide resolved
usvm-core/src/main/kotlin/org/usvm/StateForker.kt Outdated Show resolved Hide resolved
usvm-ts/src/main/kotlin/org/usvm/TSBinaryOperator.kt Outdated Show resolved Hide resolved
usvm-ts/src/main/kotlin/org/usvm/TSBinaryOperator.kt Outdated Show resolved Hide resolved

class TSTestResolver {
class TSTestResolver(
private val state: TSState
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? Resolver should be able to resolve many states independently

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TSTestResolver was instantiated for each returned state, and I needed access to state.typeStorage.
So I decided to add state as private constructor param.

usvm-ts/src/test/kotlin/org/usvm/util/TSTestResolver.kt Outdated Show resolved Hide resolved
private fun approximateParam(expr: UConcreteHeapRef, idx: Int, model: UModelBase<EtsType>): TSObject =
with(expr.ctx as TSContext) {
val suggestedType = state.getSuggestedType(idx)
return suggestedType?.let { newType ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something odd is happening here. You can always access all required information using symbolic values and symbolic values only, otherwise you will encounter path divergence. This map cannot be built from concrete values to type info, only from symbolic ones

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe different types of ref entities (reg readings, etc.) have unique ways to generate a key. For example, reg readings can use its' idx field as a key, and this key leads to correct list of types from any model.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you might store it with another key -- if I resolve something from registerReading(1), it doesn't mean that I always accessed this value using this key. Probably, I could do it with registerReading(2).getByIndex(3), i could have accessed it with RR(3) (because of aliasing) and many many other ways

@zishkaz zishkaz requested a review from CaelmBleidd October 9, 2024 11:24
Comment on lines 344 to 345
// TODO: draft
override fun internEquals(other: Any): Boolean = structurallyEqual(other)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it a draft? Seems like we can implement it

private fun generateAdditionalExprs(rawExprs: List<UExpr<out USort>>): List<UExpr<out USort>> = with(ctx) {
if (!rawExprs.all { it.sort == boolSort }) return emptyList()
val newExpr = when (baseExpr.sort) {
addressSort -> addedExprCache.putOrNull(mkEq(fpToBoolSort(asFp64()), asBool()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we need to add a connection between baseSort expr and them? If it already exists for baseSort <-> fp and bool, it exists for bool and fp by transitivity as well

usvm-ts/src/main/kotlin/org/usvm/TSExpressions.kt Outdated Show resolved Hide resolved
private fun approximateParam(expr: UConcreteHeapRef, idx: Int, model: UModelBase<EtsType>): TSObject =
with(expr.ctx as TSContext) {
val suggestedType = state.getSuggestedType(idx)
return suggestedType?.let { newType ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you might store it with another key -- if I resolve something from registerReading(1), it doesn't mean that I always accessed this value using this key. Probably, I could do it with registerReading(2).getByIndex(3), i could have accessed it with RR(3) (because of aliasing) and many many other ways


private fun approximateParam(expr: UConcreteHeapRef, idx: Int, model: UModelBase<EtsType>): TSObject =
when (val tr = model.typeStreamOf(expr).take(1)) {
is TypesResult.SuccessfulTypesResult -> with (expr.tctx) {

Check warning

Code scanning / detekt

Reports spaces around parentheses

Unexpected spacing before "("
}

val types = primitiveTypes.toMutableList()
return when (val remainingTypes = anyTypeStream.take(n - primitiveTypes.size)) {

Check warning

Code scanning / detekt

Braces do not comply with the specified policy Warning

Inconsistent braces, make sure all branches either have or don't have braces.
// (primitives can't be cast to ref in TypeScript type coercion)
addressSort -> {
val fpToBoolLink = mkEq(fpToBoolSort(asFp64()), asBool())
val boolToRefLink = mkEq(asBool(), (baseExpr as UExpr<UAddressSort>).neq(mkNullRef()))

Check warning

Code scanning / detekt

Reports multiple space usages

Unnecessary long whitespace
@@ -0,0 +1,111 @@
package org.usvm.machine.expr

import io.ksmt.KAst

Check warning

Code scanning / detekt

Detects imports in non default order

Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end
private fun coerce(
other: UExpr<out USort>,
action: CoerceAction,
): UExpr<out USort> = when (other) {

Check warning

Code scanning / detekt

Braces do not comply with the specified policy

Inconsistent braces, make sure all branches either have or don't have braces.
@@ -0,0 +1,151 @@
package org.usvm.machine.operator

import io.ksmt.utils.cast

Check warning

Code scanning / detekt

Detects imports in non default order

Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end
discoverProperties(
methodIdentifier: MethodDescriptor,
vararg analysisResultMatchers: (T1, T2, T3, T4, R?) -> Boolean,
protected inline fun <reified T1 : TSObject, reified T2 : TSObject, reified T3 : TSObject, reified T4 : TSObject, reified R : TSObject> discoverProperties(

Check warning

Code scanning / detekt

Reports lines with exceeded length Warning test

Exceeded max line length (120)
discoverProperties(
methodIdentifier: MethodDescriptor,
vararg analysisResultMatchers: (T1, T2, T3, T4, R?) -> Boolean,
protected inline fun <reified T1 : TSObject, reified T2 : TSObject, reified T3 : TSObject, reified T4 : TSObject, reified R : TSObject> discoverProperties(

Check warning

Code scanning / detekt

Line detected, which is longer than the defined maximum line length in the code style. Warning test

Line detected, which is longer than the defined maximum line length in the code style.
only KClass<TSObject> is available to match different objects.
However, this method is also used in parent TestRunner class
and passes here TSObject instances. So this check on current level is required.
*/

Check warning

Code scanning / detekt

Detect the alignment of the initial star in a block comment.

Initial star should align with start of block comment
@@ -1,5 +1,6 @@
package org.usvm.util

import io.ksmt.utils.cast

Check warning

Code scanning / detekt

Detects imports in non default order

Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end
ctx: TSContext,
model: UModelBase<EtsType>,
): List<TSObject> = with(ctx) {
params.map { param ->

Check warning

Code scanning / detekt

Reports multiple space usages

Unnecessary long whitespace
@CaelmBleidd CaelmBleidd force-pushed the sergeyl/ts_typecoercion branch from 1eed307 to b58e886 Compare December 20, 2024 16:04
@CaelmBleidd CaelmBleidd changed the base branch from main to caelmbleidd/update_kotlin_version December 20, 2024 16:05
@CaelmBleidd CaelmBleidd force-pushed the caelmbleidd/update_kotlin_version branch from 556fa95 to 703b36c Compare December 20, 2024 18:08
Base automatically changed from caelmbleidd/update_kotlin_version to main December 26, 2024 18:17
@CaelmBleidd CaelmBleidd force-pushed the sergeyl/ts_typecoercion branch from bbe7107 to aa18660 Compare January 24, 2025 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants