Skip to content

Commit e1e3ac7

Browse files
authored
Updated usvm-api and approximations (#204)
* updated usvm-api - added encoder api - added implementations for 'Engine' methods * updated approximations
1 parent 6680dc4 commit e1e3ac7

File tree

5 files changed

+85
-51
lines changed

5 files changed

+85
-51
lines changed

usvm-core/src/main/kotlin/org/usvm/api/MockApi.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ fun <Type, Method, State> StepScope<State, Type, *, *>.makeSymbolicRefWithSameTy
2828
): UHeapRef? where State : UState<Type, Method, *, *, *, State> =
2929
mockSymbolicRef { objectTypeEquals(it, representative) }
3030

31+
fun <Type, Method, State> StepScope<State, Type, *, *>.makeNullableSymbolicRefWithSameType(
32+
representative: UHeapRef
33+
): UHeapRef? where State : UState<Type, Method, *, *, *, State> =
34+
mockSymbolicRef { ctx.mkOr(objectTypeEquals(it, representative), ctx.mkEq(it, ctx.nullRef)) }
35+
3136
fun <Method> UState<*, Method, *, *, *, *>.makeSymbolicRefUntyped(): UHeapRef =
3237
memory.mocker.createMockSymbol(trackedLiteral = null, ctx.addressSort)
3338

usvm-jvm/src/main/kotlin/org/usvm/machine/JcApproximations.kt

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import kotlin.reflect.KFunction0
7070
import kotlin.reflect.KFunction1
7171
import kotlin.reflect.KFunction2
7272
import kotlin.reflect.jvm.javaMethod
73+
import org.usvm.api.makeNullableSymbolicRefWithSameType
7374

7475
class JcMethodApproximationResolver(
7576
private val ctx: JcContext,
@@ -110,63 +111,68 @@ class JcMethodApproximationResolver(
110111
}
111112

112113
private fun approximateRegularMethod(methodCall: JcMethodCall): Boolean = with(methodCall) {
113-
if (method.enclosingClass == usvmApiSymbolicList) {
114+
val enclosingClass = method.enclosingClass
115+
val className = enclosingClass.name
116+
117+
if (enclosingClass == usvmApiSymbolicList) {
114118
approximateUsvmSymbolicListMethod(methodCall)
115119
return true
116120
}
117121

118-
if (method.enclosingClass == usvmApiSymbolicMap) {
122+
if (enclosingClass == usvmApiSymbolicMap) {
119123
approximateUsvmSymbolicMapMethod(methodCall)
120124
return true
121125
}
122126

123-
if (method.enclosingClass == usvmApiSymbolicIdentityMap) {
127+
if (enclosingClass == usvmApiSymbolicIdentityMap) {
124128
approximateUsvmSymbolicIdMapMethod(methodCall)
125129
return true
126130
}
127131

128-
if (method.enclosingClass == ctx.cp.objectClass) {
132+
if (enclosingClass == ctx.cp.objectClass) {
129133
if (approximateObjectVirtualMethod(methodCall)) return true
130134
}
131135

132-
if (method.enclosingClass == ctx.classType.jcClass) {
136+
if (enclosingClass == ctx.classType.jcClass) {
133137
if (approximateClassVirtualMethod(methodCall)) return true
134138
}
135139

136-
if (method.enclosingClass.name == "jdk.internal.misc.Unsafe") {
140+
if (className == "jdk.internal.misc.Unsafe") {
137141
if (approximateUnsafeVirtualMethod(methodCall)) return true
138142
}
139143

140-
if (method.name == "clone" && method.enclosingClass == ctx.cp.objectClass) {
144+
if (method.name == "clone" && enclosingClass == ctx.cp.objectClass) {
141145
if (approximateArrayClone(methodCall)) return true
142146
}
143147

144148
return approximateEmptyNativeMethod(methodCall)
145149
}
146150

147151
private fun approximateStaticMethod(methodCall: JcMethodCall): Boolean = with(methodCall) {
148-
if (method.enclosingClass == usvmApiEngine) {
152+
val enclosingClass = method.enclosingClass
153+
val className = enclosingClass.name
154+
if (enclosingClass == usvmApiEngine) {
149155
approximateUsvmApiEngineStaticMethod(methodCall)
150156
return true
151157
}
152158

153-
if (method.enclosingClass == ctx.classType.jcClass) {
159+
if (enclosingClass == ctx.classType.jcClass) {
154160
if (approximateClassStaticMethod(methodCall)) return true
155161
}
156162

157-
if (method.enclosingClass.name == "java.lang.System") {
163+
if (className == "java.lang.System") {
158164
if (approximateSystemStaticMethod(methodCall)) return true
159165
}
160166

161-
if (method.enclosingClass.name == "java.lang.StringUTF16") {
167+
if (className == "java.lang.StringUTF16") {
162168
if (approximateStringUtf16StaticMethod(methodCall)) return true
163169
}
164170

165-
if (method.enclosingClass.name == "java.lang.Float") {
171+
if (className == "java.lang.Float") {
166172
if (approximateFloatStaticMethod(methodCall)) return true
167173
}
168174

169-
if (method.enclosingClass.name == "java.lang.Double") {
175+
if (className == "java.lang.Double") {
170176
if (approximateDoubleStaticMethod(methodCall)) return true
171177
}
172178

@@ -208,6 +214,7 @@ class JcMethodApproximationResolver(
208214
scope.doWithState {
209215
skipMethodInvocationWithValue(methodCall, classRef)
210216
}
217+
211218
return true
212219
}
213220

@@ -602,13 +609,27 @@ class JcMethodApproximationResolver(
602609
val (ref0, ref1) = it.arguments.map { it.asExpr(ctx.addressSort) }
603610
scope.calcOnState { objectTypeEquals(ref0, ref1) }
604611
}
612+
dispatchUsvmApiMethod(Engine::typeIs) {
613+
val (ref, classRef) = it.arguments.map { it.asExpr(ctx.addressSort) }
614+
val classRefTypeRepresentative = scope.calcOnState {
615+
memory.read(UFieldLValue(ctx.addressSort, classRef, ctx.classTypeSyntheticField))
616+
}
617+
scope.calcOnState { objectTypeEquals(ref, classRefTypeRepresentative) }
618+
}
605619
dispatchMkRef(Engine::makeSymbolic) {
606620
val classRef = it.arguments.single().asExpr(ctx.addressSort)
607621
val classRefTypeRepresentative = scope.calcOnState {
608622
memory.read(UFieldLValue(ctx.addressSort, classRef, ctx.classTypeSyntheticField))
609623
}
610624
scope.makeSymbolicRefWithSameType(classRefTypeRepresentative)
611625
}
626+
dispatchMkRef(Engine::makeNullableSymbolic) {
627+
val classRef = it.arguments.single().asExpr(ctx.addressSort)
628+
val classRefTypeRepresentative = scope.calcOnState {
629+
memory.read(UFieldLValue(ctx.addressSort, classRef, ctx.classTypeSyntheticField))
630+
}
631+
scope.makeNullableSymbolicRefWithSameType(classRefTypeRepresentative)
632+
}
612633
dispatchMkRef2(Engine::makeSymbolicArray) {
613634
val (elementClassRefExpr, sizeExpr) = it.arguments
614635
val elementClassRef = elementClassRefExpr.asExpr(ctx.addressSort)
Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,115 @@
11
package org.usvm.api;
22

3+
import org.usvm.api.internal.SymbolicIdentityMapImpl;
4+
import org.usvm.api.internal.SymbolicListImpl;
5+
import org.usvm.api.internal.SymbolicMapImpl;
6+
7+
import java.lang.reflect.Array;
8+
39
public class Engine {
10+
411
public static void assume(boolean expr) {
5-
engineApiStubError();
12+
assert expr;
613
}
714

15+
@SuppressWarnings("unused")
816
public static <T> T makeSymbolic(Class<T> clazz) {
9-
engineApiStubError();
17+
return null;
18+
}
19+
20+
@SuppressWarnings("unused")
21+
public static <T> T makeNullableSymbolic(Class<T> clazz) {
1022
return null;
1123
}
1224

1325
public static boolean makeSymbolicBoolean() {
14-
engineApiStubError();
1526
return false;
1627
}
1728

1829
public static byte makeSymbolicByte() {
19-
engineApiStubError();
2030
return 0;
2131
}
2232

2333
public static char makeSymbolicChar() {
24-
engineApiStubError();
2534
return 0;
2635
}
2736

2837
public static short makeSymbolicShort() {
29-
engineApiStubError();
3038
return 0;
3139
}
3240

3341
public static int makeSymbolicInt() {
34-
engineApiStubError();
3542
return 0;
3643
}
3744

3845
public static long makeSymbolicLong() {
39-
engineApiStubError();
4046
return 0;
4147
}
4248

4349
public static float makeSymbolicFloat() {
44-
engineApiStubError();
4550
return 0;
4651
}
4752

4853
public static double makeSymbolicDouble() {
49-
engineApiStubError();
5054
return 0;
5155
}
5256

57+
@SuppressWarnings("unchecked")
5358
public static <T> T[] makeSymbolicArray(Class<T> clazz, int size) {
54-
engineApiStubError();
55-
return null;
59+
assert clazz.isArray();
60+
61+
return (T[]) Array.newInstance(clazz, size);
5662
}
5763

5864
public static boolean[] makeSymbolicBooleanArray(int size) {
59-
engineApiStubError();
60-
return null;
65+
return new boolean[size];
6166
}
6267

6368
public static byte[] makeSymbolicByteArray(int size) {
64-
engineApiStubError();
65-
return null;
69+
return new byte[size];
6670
}
6771

6872
public static char[] makeSymbolicCharArray(int size) {
69-
engineApiStubError();
70-
return null;
73+
return new char[size];
7174
}
7275

7376
public static short[] makeSymbolicShortArray(int size) {
74-
engineApiStubError();
75-
return null;
77+
return new short[size];
7678
}
7779

7880
public static int[] makeSymbolicIntArray(int size) {
79-
engineApiStubError();
80-
return null;
81+
return new int[size];
8182
}
8283

8384
public static long[] makeSymbolicLongArray(int size) {
84-
engineApiStubError();
85-
return null;
85+
return new long[size];
8686
}
8787

8888
public static float[] makeSymbolicFloatArray(int size) {
89-
engineApiStubError();
90-
return null;
89+
return new float[size];
9190
}
9291

9392
public static double[] makeSymbolicDoubleArray(int size) {
94-
engineApiStubError();
95-
return null;
93+
return new double[size];
9694
}
9795

9896
public static <T> SymbolicList<T> makeSymbolicList() {
99-
engineApiStubError();
100-
return null;
97+
return new SymbolicListImpl<>();
10198
}
10299

103100
public static <K, V> SymbolicMap<K, V> makeSymbolicMap() {
104-
engineApiStubError();
105-
return null;
101+
return new SymbolicMapImpl<>();
106102
}
107103

108104
public static <K, V> SymbolicIdentityMap<K, V> makeSymbolicIdentityMap() {
109-
engineApiStubError();
110-
return null;
105+
return new SymbolicIdentityMapImpl<>();
111106
}
112107

113108
public static boolean typeEquals(Object a, Object b) {
114-
engineApiStubError();
115-
return false;
109+
return a.getClass() == b.getClass();
116110
}
117111

118-
private static void engineApiStubError() {
119-
throw new IllegalStateException("Engine API method must not be invoked");
112+
public static boolean typeIs(Object a, Class<?> type) {
113+
return a.getClass() == type;
120114
}
121115
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.usvm.api.encoder;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Target;
5+
6+
@Target({ElementType.TYPE})
7+
public @interface EncoderFor {
8+
Class<?> value();
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.usvm.api.encoder;
2+
3+
public interface ObjectEncoder {
4+
Object encode(Object object);
5+
}

0 commit comments

Comments
 (0)