From dc689ff51487bf75f66bd57f6aec83e3541b68ce Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 16 Aug 2016 20:05:23 +0300 Subject: [PATCH] Fix concurrent access issues in CallableReference implementations Because of multiple reads from the same non-volatile variable, NPE was possible to achieve in a multi-threaded application --- .../jvm/internal/CallableReference.java | 14 ++++++++------ .../jvm/internal/FunctionReference.java | 19 ++++++++++--------- .../jvm/internal/PropertyReference.java | 3 ++- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java index 1e493b8a609..da51704a44c 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java @@ -122,17 +122,19 @@ public abstract class CallableReference implements KCallable { } public KCallable compute() { - if (reflected == null) { - reflected = computeReflected(); + KCallable result = reflected; + if (result == null) { + result = computeReflected(); + reflected = result; } - return reflected; + return result; } protected KCallable getReflected() { - compute(); - if (reflected == this) { + KCallable result = compute(); + if (result == this) { throw new KotlinReflectionNotSupportedError(); } - return reflected; + return result; } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java index 771c26c17a8..f4374230b64 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java @@ -146,8 +146,7 @@ public class FunctionReference extends FunctionImpl implements KFunction { getSignature().equals(other.getSignature()); } if (obj instanceof KFunction) { - compute(); - return obj.equals(reflected); + return obj.equals(compute()); } return false; } @@ -159,7 +158,7 @@ public class FunctionReference extends FunctionImpl implements KFunction { @Override public String toString() { - compute(); + KFunction reflected = compute(); if (reflected != this) { return reflected.toString(); } @@ -171,17 +170,19 @@ public class FunctionReference extends FunctionImpl implements KFunction { } public KFunction compute() { - if (reflected == null) { - reflected = Reflection.function(this); + KFunction result = reflected; + if (result == null) { + result = Reflection.function(this); + reflected = result; } - return reflected; + return result; } private KFunction getReflected() { - compute(); - if (reflected == this) { + KFunction result = compute(); + if (result == this) { throw new KotlinReflectionNotSupportedError(); } - return reflected; + return result; } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java index 09454de0e69..3341ea18968 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java @@ -16,6 +16,7 @@ package kotlin.jvm.internal; +import kotlin.reflect.KCallable; import kotlin.reflect.KProperty; public abstract class PropertyReference extends CallableReference implements KProperty { @@ -57,7 +58,7 @@ public abstract class PropertyReference extends CallableReference implements KPr @Override public String toString() { - compute(); + KCallable reflected = compute(); if (reflected != this) { return reflected.toString(); }