|
1 | 1 | package org.utbot.engine
|
2 | 2 |
|
3 | 3 | import kotlinx.collections.immutable.persistentHashMapOf
|
| 4 | +import kotlinx.collections.immutable.persistentHashSetOf |
4 | 5 | import kotlinx.collections.immutable.persistentListOf
|
5 | 6 | import kotlinx.collections.immutable.persistentSetOf
|
6 | 7 | import kotlinx.collections.immutable.toPersistentList
|
7 |
| -import kotlinx.collections.immutable.toPersistentMap |
8 | 8 | import kotlinx.collections.immutable.toPersistentSet
|
9 | 9 | import org.utbot.common.WorkaroundReason.HACK
|
| 10 | +import org.utbot.framework.UtSettings.ignoreStaticsFromTrustedLibraries |
| 11 | +import org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES |
10 | 12 | import org.utbot.common.WorkaroundReason.REMOVE_ANONYMOUS_CLASSES
|
11 | 13 | import org.utbot.common.unreachableBranch
|
12 | 14 | import org.utbot.common.withAccessibility
|
@@ -112,6 +114,7 @@ import soot.DoubleType
|
112 | 114 | import soot.FloatType
|
113 | 115 | import soot.IntType
|
114 | 116 | import soot.LongType
|
| 117 | +import soot.Modifier |
115 | 118 | import soot.PrimType
|
116 | 119 | import soot.RefLikeType
|
117 | 120 | import soot.RefType
|
@@ -560,7 +563,7 @@ class Traverser(
|
560 | 563 | }
|
561 | 564 |
|
562 | 565 | val initializedStaticFieldsMemoryUpdate = MemoryUpdate(
|
563 |
| - initializedStaticFields = staticFields.associate { it.first.fieldId to it.second.single() }.toPersistentMap(), |
| 566 | + initializedStaticFields = staticFields.map { it.first.fieldId }.toPersistentSet(), |
564 | 567 | meaningfulStaticFields = meaningfulStaticFields.map { it.first.fieldId }.toPersistentSet(),
|
565 | 568 | symbolicEnumValues = enumConstantSymbolicValues.toPersistentList()
|
566 | 569 | )
|
@@ -596,7 +599,7 @@ class Traverser(
|
596 | 599 |
|
597 | 600 | // Collects memory updates
|
598 | 601 | val initializedFieldUpdate =
|
599 |
| - MemoryUpdate(initializedStaticFields = persistentHashMapOf(fieldId to concreteValue)) |
| 602 | + MemoryUpdate(initializedStaticFields = persistentHashSetOf(fieldId)) |
600 | 603 |
|
601 | 604 | val objectUpdate = objectUpdate(
|
602 | 605 | instance = findOrCreateStaticObject(declaringClass.type),
|
@@ -823,7 +826,7 @@ class Traverser(
|
823 | 826 | val staticFieldMemoryUpdate = StaticFieldMemoryUpdateInfo(fieldId, value)
|
824 | 827 | val touchedStaticFields = persistentListOf(staticFieldMemoryUpdate)
|
825 | 828 | queuedSymbolicStateUpdates += MemoryUpdate(staticFieldsUpdates = touchedStaticFields)
|
826 |
| - if (!environment.method.isStaticInitializer && !fieldId.isSynthetic) { |
| 829 | + if (!environment.method.isStaticInitializer && isStaticFieldMeaningful(left.field)) { |
827 | 830 | queuedSymbolicStateUpdates += MemoryUpdate(meaningfulStaticFields = persistentSetOf(fieldId))
|
828 | 831 | }
|
829 | 832 | }
|
@@ -1780,13 +1783,27 @@ class Traverser(
|
1780 | 1783 | queuedSymbolicStateUpdates += MemoryUpdate(staticFieldsUpdates = touchedStaticFields)
|
1781 | 1784 |
|
1782 | 1785 | // TODO filter enum constant static fields JIRA:1681
|
1783 |
| - if (!environment.method.isStaticInitializer && !fieldId.isSynthetic) { |
| 1786 | + if (!environment.method.isStaticInitializer && isStaticFieldMeaningful(field)) { |
1784 | 1787 | queuedSymbolicStateUpdates += MemoryUpdate(meaningfulStaticFields = persistentSetOf(fieldId))
|
1785 | 1788 | }
|
1786 | 1789 |
|
1787 | 1790 | return createdField
|
1788 | 1791 | }
|
1789 | 1792 |
|
| 1793 | + /** |
| 1794 | + * For now the field is `meaningful` if it is safe to set, that is, it is not an internal system field nor a |
| 1795 | + * synthetic field. This filter is needed to prohibit changing internal fields, which can break up our own |
| 1796 | + * code and which are useless for the user. |
| 1797 | + * |
| 1798 | + * @return `true` if the field is meaningful, `false` otherwise. |
| 1799 | + */ |
| 1800 | + private fun isStaticFieldMeaningful(field: SootField) = |
| 1801 | + !Modifier.isSynthetic(field.modifiers) && |
| 1802 | + // we don't want to set fields from library classes |
| 1803 | + !workaround(IGNORE_STATICS_FROM_TRUSTED_LIBRARIES) { |
| 1804 | + ignoreStaticsFromTrustedLibraries && field.declaringClass.isFromTrustedLibrary() |
| 1805 | + } |
| 1806 | + |
1790 | 1807 | /**
|
1791 | 1808 | * Locates object represents static fields of particular class.
|
1792 | 1809 | *
|
@@ -3321,10 +3338,11 @@ class Traverser(
|
3321 | 3338 | val updatedFields = staticFieldsUpdates.mapTo(mutableSetOf()) { it.fieldId }
|
3322 | 3339 | val objectUpdates = mutableListOf<UtNamedStore>()
|
3323 | 3340 |
|
3324 |
| - // we assign unbounded symbolic variables for every non-final field of the class |
| 3341 | + // we assign unbounded symbolic variables for every non-final meaningful field of the class |
| 3342 | + // fields from predefined library classes are excluded, because there are not meaningful |
3325 | 3343 | typeResolver
|
3326 | 3344 | .findFields(declaringClass.type)
|
3327 |
| - .filter { !it.isFinal && it.fieldId in updatedFields } |
| 3345 | + .filter { !it.isFinal && it.fieldId in updatedFields && isStaticFieldMeaningful(it) } |
3328 | 3346 | .forEach {
|
3329 | 3347 | // remove updates from clinit, because we'll replace those values
|
3330 | 3348 | // with new unbounded symbolic variable
|
|
0 commit comments