Do not allow to assign null to a non-null property via reflection

This was already working for accessor-based properties because the assertions
were already generated into corresponding accessors, but for fields we must
manually check the value against null
This commit is contained in:
Alexander Udalov
2015-08-04 21:09:09 +03:00
parent 3091f2af3b
commit 49b689f883
4 changed files with 67 additions and 6 deletions
@@ -102,8 +102,16 @@ internal sealed class FunctionCaller(
abstract class FieldSetter(
field: ReflectField,
private val notNull: Boolean,
private val requiresInstance: Boolean
) : FieldAccessor(field, if (requiresInstance) 2 else 1) {
override fun checkArguments(args: Array<*>) {
super.checkArguments(args)
if (notNull && args.last() == null) {
throw IllegalArgumentException("null is not allowed as a value for this property.")
}
}
override fun call(args: Array<*>): Any? {
checkArguments(args)
return field.set(if (requiresInstance) args.first() else null, args.last())
@@ -121,11 +129,11 @@ internal sealed class FunctionCaller(
}
}
class StaticFieldSetter(field: ReflectField) : FieldSetter(field, requiresInstance = false)
class StaticFieldSetter(field: ReflectField, notNull: Boolean) : FieldSetter(field, notNull, requiresInstance = false)
class InstanceFieldSetter(field: ReflectField) : FieldSetter(field, requiresInstance = true)
class InstanceFieldSetter(field: ReflectField, notNull: Boolean) : FieldSetter(field, notNull, requiresInstance = true)
class PlatformStaticInObjectFieldSetter(field: ReflectField) : FieldSetter(field, requiresInstance = true) {
class PlatformStaticInObjectFieldSetter(field: ReflectField, notNull: Boolean) : FieldSetter(field, notNull, requiresInstance = true) {
override fun checkArguments(args: Array<*>) {
super.checkArguments(args)
checkObjectInstance(args.firstOrNull())
@@ -18,6 +18,7 @@ package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.types.TypeUtils
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import kotlin.reflect.KMutableProperty
@@ -81,16 +82,19 @@ private fun KPropertyImpl.Accessor<*>.computeCallerForAccessor(isGetter: Boolean
fun isPlatformStaticProperty() =
property.descriptor.annotations.findAnnotation(PLATFORM_STATIC) != null
fun isNotNullProperty() =
!TypeUtils.isNullableType(property.descriptor.type)
fun computeFieldCaller(field: Field): FunctionCaller.FieldAccessor = when {
!Modifier.isStatic(field.modifiers) ->
if (isGetter) FunctionCaller.InstanceFieldGetter(field)
else FunctionCaller.InstanceFieldSetter(field)
else FunctionCaller.InstanceFieldSetter(field, isNotNullProperty())
isPlatformStaticProperty() ->
if (isGetter) FunctionCaller.PlatformStaticInObjectFieldGetter(field)
else FunctionCaller.PlatformStaticInObjectFieldSetter(field)
else FunctionCaller.PlatformStaticInObjectFieldSetter(field, isNotNullProperty())
else ->
if (isGetter) FunctionCaller.StaticFieldGetter(field)
else FunctionCaller.StaticFieldSetter(field)
else FunctionCaller.StaticFieldSetter(field, isNotNullProperty())
}
val jvmSignature = RuntimeTypeMapper.mapPropertySignature(property.descriptor)