diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ValueConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ValueConstructor.kt index a3301c1828..445a5145f4 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/ValueConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ValueConstructor.kt @@ -1,7 +1,6 @@ package org.utbot.engine import org.utbot.common.invokeCatching -import org.utbot.common.withAccessibility import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.ConstructorId import org.utbot.framework.plugin.api.EnvironmentModels @@ -41,6 +40,7 @@ import org.utbot.framework.plugin.api.util.jClass import org.utbot.framework.plugin.api.util.method import org.utbot.framework.plugin.api.util.utContext import org.utbot.framework.util.anyInstance +import org.utbot.instrumentation.process.runSandbox import java.lang.reflect.Field import java.lang.reflect.Modifier import kotlin.reflect.KClass @@ -405,17 +405,13 @@ class ValueConstructor { private fun value(model: UtModel) = construct(model, null).value private fun MethodId.call(args: List, instance: Any?): Any? = - method.run { - withAccessibility { - invokeCatching(obj = instance, args = args).getOrThrow() - } + method.runSandbox { + invokeCatching(obj = instance, args = args).getOrThrow() } private fun ConstructorId.call(args: List): Any? = - constructor.run { - withAccessibility { - newInstance(*args.toTypedArray()) - } + constructor.runSandbox { + newInstance(*args.toTypedArray()) } /** diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/MockValueConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/MockValueConstructor.kt index eca3609bd9..8bf5b4fc12 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/MockValueConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/MockValueConstructor.kt @@ -44,7 +44,7 @@ import kotlin.reflect.KClass import org.mockito.Mockito import org.mockito.stubbing.Answer import org.objectweb.asm.Type -import org.utbot.common.withAccessibility +import org.utbot.instrumentation.process.runSandbox /** * Constructs values (including mocks) from models. @@ -441,17 +441,13 @@ class MockValueConstructor( } private fun MethodId.call(args: List, instance: Any?): Any? = - method.run { - withAccessibility { - invokeCatching(obj = instance, args = args).getOrThrow() - } + method.runSandbox { + invokeCatching(obj = instance, args = args).getOrThrow() } private fun ConstructorId.call(args: List): Any? = - constructor.run { - withAccessibility { - newInstance(*args.toTypedArray()) - } + constructor.runSandbox { + newInstance(*args.toTypedArray()) } /** diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt index 6cd1b1e800..3627fe5aa6 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt @@ -43,6 +43,7 @@ import java.security.AccessControlException import java.security.ProtectionDomain import java.util.IdentityHashMap import org.objectweb.asm.Type +import org.utbot.framework.plugin.api.MissingState import kotlin.reflect.jvm.javaMethod /** @@ -144,7 +145,18 @@ object UtExecutionInstrumentation : Instrumentation { traceHandler.resetTrace() return MockValueConstructor(instrumentationContext).use { constructor -> - val params = constructor.constructMethodParameters(parametersModels) + val params = try { + constructor.constructMethodParameters(parametersModels) + } catch (e: Throwable) { + if (e.cause is AccessControlException) { + return@use UtConcreteExecutionResult( + MissingState, + UtSandboxFailure(e.cause!!), + Coverage() + ) + } + throw e + } val staticFields = constructor .constructStatics( stateBefore diff --git a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/InvokeInstrumentation.kt b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/InvokeInstrumentation.kt index 0fd8e5bb3d..1e145c0ea6 100644 --- a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/InvokeInstrumentation.kt +++ b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/InvokeInstrumentation.kt @@ -1,8 +1,7 @@ package org.utbot.instrumentation.instrumentation -import org.utbot.common.withAccessibility import org.utbot.framework.plugin.api.util.signature -import org.utbot.instrumentation.process.sandbox +import org.utbot.instrumentation.process.runSandbox import java.lang.reflect.Constructor import java.lang.reflect.InvocationTargetException import java.lang.reflect.Method @@ -53,18 +52,18 @@ class InvokeInstrumentation : Instrumentation> { methodOrConstructor.run { val result = when (this) { is Method -> - withAccessibility { + runSandbox { runCatching { - sandbox { invoke(thisObject, *realArgs.toTypedArray()) }.let { + invoke(thisObject, *realArgs.toTypedArray()).let { if (returnType != Void.TYPE) it else Unit } // invocation on method returning void will return null, so we replace it with Unit } } is Constructor<*> -> - withAccessibility { + runSandbox { runCatching { - sandbox { newInstance(*realArgs.toTypedArray()) } + newInstance(*realArgs.toTypedArray()) } } diff --git a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/process/Security.kt b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/process/Security.kt index f94bfb06e6..70bc6b2e3a 100644 --- a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/process/Security.kt +++ b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/process/Security.kt @@ -2,7 +2,9 @@ package org.utbot.instrumentation.process +import org.utbot.common.withAccessibility import sun.security.provider.PolicyFile +import java.lang.reflect.AccessibleObject import java.net.URI import java.nio.file.Files import java.nio.file.Paths @@ -28,6 +30,15 @@ internal fun permissions(block: SimplePolicy.() -> Unit) { } } +/** + * Make this [AccessibleObject] accessible and run a block inside sandbox. + */ +fun O.runSandbox(block: O.() -> R): R { + return withAccessibility { + sandbox { block() } + } +} + /** * Run [block] in sandbox mode. * @@ -45,15 +56,17 @@ internal fun permissions(block: SimplePolicy.() -> Unit) { * ``` * Read more [about policy file and syntax](https://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html#Examples) */ -internal fun sandbox(block: () -> T): T { +fun sandbox(block: () -> T): T { val policyPath = Paths.get(System.getProperty("user.home"), ".utbot", "sandbox.policy") return sandbox(policyPath.toUri()) { block() } } -internal fun sandbox(file: URI, block: () -> T): T { +fun sandbox(file: URI, block: () -> T): T { val path = Paths.get(file) val perms = mutableListOf( - RuntimePermission("accessDeclaredMembers") + RuntimePermission("accessDeclaredMembers"), + RuntimePermission("getStackWalkerWithClassReference"), + RuntimePermission("getClassLoader"), ) val allCodeSource = CodeSource(null, emptyArray()) if (Files.exists(path)) { @@ -64,12 +77,12 @@ internal fun sandbox(file: URI, block: () -> T): T { return sandbox(perms, allCodeSource) { block() } } -internal fun sandbox(permission: List, cs: CodeSource, block: () -> T): T { +fun sandbox(permission: List, cs: CodeSource, block: () -> T): T { val perms = permission.fold(Permissions()) { acc, p -> acc.add(p); acc } return sandbox(perms, cs) { block() } } -internal fun sandbox(perms: PermissionCollection, cs: CodeSource, block: () -> T): T { +fun sandbox(perms: PermissionCollection, cs: CodeSource, block: () -> T): T { val acc = AccessControlContext(arrayOf(ProtectionDomain(cs, perms))) return try { AccessController.doPrivileged(PrivilegedAction { block() }, acc)