Reflection: fix exceptions on concurrent access to some properties

Using `ReflectionProperties.lazy` is incorrect because it allows several
threads to observe different resulting values if they're computing it
simultaneously (unlike `lazy(PUBLICATION)`, which always returns the
value that "won the race").

In the case of property delegates, for example, if we're invoking
`isAccessible = true` and then `getDelegate()` concurrently, it might
happen that when some thread invokes `getDelegate()`, it gets the
underlying Field object which was written by another thread and which
has not yet been made accessible, leading to
IllegalPropertyDelegateAccessException.

 #KT-27585 Fixed
This commit is contained in:
Alexander Udalov
2023-01-24 16:34:00 +01:00
committed by Space Team
parent e8f95a3376
commit 99b38ccb74
9 changed files with 137 additions and 31 deletions
@@ -23,6 +23,7 @@ import java.lang.reflect.Constructor
import java.lang.reflect.Member
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.jvm.internal.CallableReference
import kotlin.jvm.internal.FunctionBase
import kotlin.reflect.KFunction
@@ -58,7 +59,7 @@ internal class KFunctionImpl private constructor(
override val name: String get() = descriptor.name.asString()
override val caller: Caller<*> by ReflectProperties.lazy caller@{
override val caller: Caller<*> by lazy(PUBLICATION) caller@{
val member: Member? = when (val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)) {
is KotlinConstructor -> {
if (isAnnotationConstructor)
@@ -89,7 +90,7 @@ internal class KFunctionImpl private constructor(
}.createInlineClassAwareCallerIfNeeded(descriptor)
}
override val defaultCaller: Caller<*>? by ReflectProperties.lazy defaultCaller@{
override val defaultCaller: Caller<*>? by lazy(PUBLICATION) defaultCaller@{
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
val member: Member? = when (jvmSignature) {
is KotlinFunction -> {
@@ -28,9 +28,9 @@ internal open class KProperty0Impl<out V> : KProperty0<V>, KPropertyImpl<V> {
container, name, signature, boundReceiver
)
private val _getter = ReflectProperties.lazy { Getter(this) }
private val _getter = lazy(PUBLICATION) { Getter(this) }
override val getter: Getter<V> get() = _getter()
override val getter: Getter<V> get() = _getter.value
override fun get(): V = getter.call()
@@ -52,9 +52,9 @@ internal class KMutableProperty0Impl<V> : KProperty0Impl<V>, KMutableProperty0<V
container, name, signature, boundReceiver
)
private val _setter = ReflectProperties.lazy { Setter(this) }
private val _setter = lazy(PUBLICATION) { Setter(this) }
override val setter: Setter<V> get() = _setter()
override val setter: Setter<V> get() = _setter.value
override fun set(value: V) = setter.call(value)
@@ -28,9 +28,9 @@ internal open class KProperty1Impl<T, out V> : KProperty1<T, V>, KPropertyImpl<V
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
private val _getter = ReflectProperties.lazy { Getter(this) }
private val _getter = lazy(PUBLICATION) { Getter(this) }
override val getter: Getter<T, V> get() = _getter()
override val getter: Getter<T, V> get() = _getter.value
override fun get(receiver: T): V = getter.call(receiver)
@@ -52,9 +52,9 @@ internal class KMutableProperty1Impl<T, V> : KProperty1Impl<T, V>, KMutablePrope
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
private val _setter = ReflectProperties.lazy { Setter(this) }
private val _setter = lazy(PUBLICATION) { Setter(this) }
override val setter: Setter<T, V> get() = _setter()
override val setter: Setter<T, V> get() = _setter.value
override fun set(receiver: T, value: V) = setter.call(receiver, value)
@@ -29,9 +29,9 @@ internal open class KProperty2Impl<D, E, out V> : KProperty2<D, E, V>, KProperty
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
private val _getter = ReflectProperties.lazy { Getter(this) }
private val _getter = lazy(PUBLICATION) { Getter(this) }
override val getter: Getter<D, E, V> get() = _getter()
override val getter: Getter<D, E, V> get() = _getter.value
override fun get(receiver1: D, receiver2: E): V = getter.call(receiver1, receiver2)
@@ -51,9 +51,9 @@ internal class KMutableProperty2Impl<D, E, V> : KProperty2Impl<D, E, V>, KMutabl
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
private val _setter = ReflectProperties.lazy { Setter(this) }
private val _setter = lazy(PUBLICATION) { Setter(this) }
override val setter: Setter<D, E, V> get() = _setter()
override val setter: Setter<D, E, V> get() = _setter.value
override fun set(receiver1: D, receiver2: E, value: V) = setter.call(receiver1, receiver2, value)
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.resolve.isUnderlyingPropertyOfInlineClass
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
import org.jetbrains.kotlin.types.TypeUtils
import java.lang.reflect.*
import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.jvm.internal.CallableReference
import kotlin.reflect.KFunction
import kotlin.reflect.KMutableProperty
@@ -48,7 +49,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
override val isBound: Boolean get() = rawBoundReceiver != CallableReference.NO_RECEIVER
private val _javaField: ReflectProperties.LazyVal<Field?> = ReflectProperties.lazy {
private val _javaField = lazy(PUBLICATION) {
when (val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor)) {
is KotlinProperty -> {
val descriptor = jvmSignature.descriptor
@@ -75,7 +76,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
}
}
val javaField: Field? get() = _javaField()
val javaField: Field? get() = _javaField.value
protected fun computeDelegateSource(): Member? {
if (!descriptor.isDelegated) return null
@@ -175,7 +176,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
property.descriptor.getter ?: DescriptorFactory.createDefaultGetter(property.descriptor, Annotations.EMPTY)
}
override val caller: Caller<*> by ReflectProperties.lazy {
override val caller: Caller<*> by lazy(PUBLICATION) {
computeCallerForAccessor(isGetter = true)
}
@@ -196,7 +197,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
property.descriptor.setter ?: DescriptorFactory.createDefaultSetter(property.descriptor, Annotations.EMPTY, Annotations.EMPTY)
}
override val caller: Caller<*> by ReflectProperties.lazy {
override val caller: Caller<*> by lazy(PUBLICATION) {
computeCallerForAccessor(isGetter = false)
}