@@ -88,8 +88,10 @@ import org.utbot.engine.symbolic.asUpdate
88
88
import org.utbot.engine.simplificators.MemoryUpdateSimplificator
89
89
import org.utbot.engine.simplificators.simplifySymbolicStateUpdate
90
90
import org.utbot.engine.simplificators.simplifySymbolicValue
91
+ import org.utbot.engine.types.CLASS_REF_TYPE
91
92
import org.utbot.engine.types.ENUM_ORDINAL
92
93
import org.utbot.engine.types.EQUALS_SIGNATURE
94
+ import org.utbot.engine.types.NEW_INSTANCE_SIGNATURE
93
95
import org.utbot.engine.types.HASHCODE_SIGNATURE
94
96
import org.utbot.engine.types.METHOD_FILTER_MAP_FIELD_SIGNATURE
95
97
import org.utbot.engine.types.NUMBER_OF_PREFERRED_TYPES
@@ -340,7 +342,8 @@ class Traverser(
340
342
}
341
343
342
344
/* *
343
- * Handles preparatory work for static initializers and multi-dimensional arrays creation.
345
+ * Handles preparatory work for static initializers, multi-dimensional arrays creation
346
+ * and `newInstance` reflection call post-processing.
344
347
*
345
348
* For instance, it could push handmade graph with preparation statements to the path selector.
346
349
*
@@ -356,6 +359,7 @@ class Traverser(
356
359
return when {
357
360
processStaticInitializerIfRequired(current) -> true
358
361
unfoldMultiArrayExprIfRequired(current) -> true
362
+ pushInitGraphAfterNewInstanceReflectionCall(current) -> true
359
363
else -> false
360
364
}
361
365
}
@@ -411,6 +415,50 @@ class Traverser(
411
415
return true
412
416
}
413
417
418
+ /* *
419
+ * If the previous stms was `newInstance` method invocation,
420
+ * pushes a graph of the default constructor of the constructed type, if present,
421
+ * and pushes a state with a [InstantiationException] otherwise.
422
+ */
423
+ private fun TraversalContext.pushInitGraphAfterNewInstanceReflectionCall (stmt : JAssignStmt ): Boolean {
424
+ // Check whether the previous stmt was a `newInstance` invocation
425
+ val lastStmt = environment.state.path.lastOrNull() as ? JAssignStmt ? : return false
426
+ val lastStmtRight = lastStmt.rightOp as ? JVirtualInvokeExpr ? : return false
427
+ val lastMethodInvocation = lastStmtRight.retrieveMethod()
428
+ if (lastMethodInvocation.subSignature != NEW_INSTANCE_SIGNATURE ) {
429
+ return false
430
+ }
431
+
432
+ // Process the current stmt as cast expression
433
+ val right = stmt.rightOp as ? JCastExpr ? : return false
434
+ val castType = right.castType as ? RefType ? : return false
435
+ val castedJimpleVariable = right.op as ? JimpleLocal ? : return false
436
+
437
+ val castedLocalVariable = (localVariableMemory.local(castedJimpleVariable.variable) as ? ReferenceValue ) ? : return false
438
+
439
+ val castSootClass = castType.sootClass
440
+
441
+ // We need to consider a situation when this class does not have a default constructor
442
+ // Since it can be a cast of a class with constructor to the interface (or ot the ancestor without default constructor),
443
+ // we cannot always throw a `java.lang.InstantiationException`.
444
+ // So, instead we will just continue the analysis without analysis of <init>.
445
+ val initMethod = castSootClass.getMethodUnsafe(" void <init>()" ) ? : return false
446
+
447
+ if (! initMethod.canRetrieveBody()) {
448
+ return false
449
+ }
450
+
451
+ val initGraph = ExceptionalUnitGraph (initMethod.activeBody)
452
+
453
+ pushToPathSelector(
454
+ initGraph,
455
+ castedLocalVariable,
456
+ callParameters = emptyList(),
457
+ )
458
+
459
+ return true
460
+ }
461
+
414
462
/* *
415
463
* Processes static initialization for class.
416
464
*
@@ -2915,6 +2963,21 @@ class Traverser(
2915
2963
}
2916
2964
}
2917
2965
2966
+ // Return an unbounded symbolic variable for any `forName` overloading
2967
+ if (instance == null && invocation.method.name == " forName" ) {
2968
+ val forNameResult = unboundedVariable(name = " classForName" , invocation.method)
2969
+
2970
+ return OverrideResult (success = true , forNameResult)
2971
+ }
2972
+
2973
+ // Return an unbounded symbolic variable for the `newInstance` method invocation,
2974
+ // and at the next traversing step push <init> graph of the resulted type
2975
+ if (instance?.type == CLASS_REF_TYPE && subSignature == NEW_INSTANCE_SIGNATURE ) {
2976
+ val getInstanceResult = unboundedVariable(name = " newInstance" , invocation.method)
2977
+
2978
+ return OverrideResult (success = true , getInstanceResult)
2979
+ }
2980
+
2918
2981
val instanceAsWrapperOrNull = instance?.asWrapperOrNull
2919
2982
2920
2983
if (instanceAsWrapperOrNull is UtMockWrapper && subSignature == HASHCODE_SIGNATURE ) {
0 commit comments