Reflection: fix callBy for functions with 32 * N parameters

Optimization in 2439c22ff6 introduced an array `absentArguments` with
default values of all parameter types, which is copied in `callBy`
instead of being recomputed each time. Unfortunately, its size was
computed incorrectly: `maskSize` should only take into account
value parameters (see the `parameter.kind == KParameter.Kind.VALUE`
check in `callBy`).

This led to an issue where if the function had 32 * N value parameters
and 1 receiver parameter, `maskSize` was greater by 1 than expected,
which caused an exception due to mismatching argument array sizes.

 #KT-61304 Fixed
This commit is contained in:
Alexander Udalov
2023-08-31 17:59:30 +02:00
committed by Space Team
parent 421cd9929b
commit 34f52aaeda
10 changed files with 201 additions and 1 deletions
@@ -113,9 +113,16 @@ internal abstract class KCallableImpl<out R> : KCallable<R>, KTypeParameterOwner
}
private val _absentArguments = ReflectProperties.lazySoft {
val parameters = parameters
val parameterSize = parameters.size + (if (isSuspend) 1 else 0)
val flattenedParametersSize =
if (parametersNeedMFVCFlattening.value) parameters.sumOf { getParameterTypeSize(it) } else parameters.size
if (parametersNeedMFVCFlattening.value) {
parameters.sumOf {
if (it.kind == KParameter.Kind.VALUE) getParameterTypeSize(it) else 0
}
} else {
parameters.count { it.kind == KParameter.Kind.VALUE }
}
val maskSize = (flattenedParametersSize + Integer.SIZE - 1) / Integer.SIZE
// Array containing the actual function arguments, masks, and +1 for DefaultConstructorMarker or MethodHandle.