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
This commit is contained in:
Alexander Udalov
2016-08-16 20:05:23 +03:00
parent 8fb5858dae
commit dc689ff514
3 changed files with 20 additions and 16 deletions
@@ -122,17 +122,19 @@ public abstract class CallableReference implements KCallable {
} }
public KCallable compute() { public KCallable compute() {
if (reflected == null) { KCallable result = reflected;
reflected = computeReflected(); if (result == null) {
result = computeReflected();
reflected = result;
} }
return reflected; return result;
} }
protected KCallable getReflected() { protected KCallable getReflected() {
compute(); KCallable result = compute();
if (reflected == this) { if (result == this) {
throw new KotlinReflectionNotSupportedError(); throw new KotlinReflectionNotSupportedError();
} }
return reflected; return result;
} }
} }
@@ -146,8 +146,7 @@ public class FunctionReference extends FunctionImpl implements KFunction {
getSignature().equals(other.getSignature()); getSignature().equals(other.getSignature());
} }
if (obj instanceof KFunction) { if (obj instanceof KFunction) {
compute(); return obj.equals(compute());
return obj.equals(reflected);
} }
return false; return false;
} }
@@ -159,7 +158,7 @@ public class FunctionReference extends FunctionImpl implements KFunction {
@Override @Override
public String toString() { public String toString() {
compute(); KFunction reflected = compute();
if (reflected != this) { if (reflected != this) {
return reflected.toString(); return reflected.toString();
} }
@@ -171,17 +170,19 @@ public class FunctionReference extends FunctionImpl implements KFunction {
} }
public KFunction compute() { public KFunction compute() {
if (reflected == null) { KFunction result = reflected;
reflected = Reflection.function(this); if (result == null) {
result = Reflection.function(this);
reflected = result;
} }
return reflected; return result;
} }
private KFunction getReflected() { private KFunction getReflected() {
compute(); KFunction result = compute();
if (reflected == this) { if (result == this) {
throw new KotlinReflectionNotSupportedError(); throw new KotlinReflectionNotSupportedError();
} }
return reflected; return result;
} }
} }
@@ -16,6 +16,7 @@
package kotlin.jvm.internal; package kotlin.jvm.internal;
import kotlin.reflect.KCallable;
import kotlin.reflect.KProperty; import kotlin.reflect.KProperty;
public abstract class PropertyReference extends CallableReference implements KProperty { public abstract class PropertyReference extends CallableReference implements KProperty {
@@ -57,7 +58,7 @@ public abstract class PropertyReference extends CallableReference implements KPr
@Override @Override
public String toString() { public String toString() {
compute(); KCallable reflected = compute();
if (reflected != this) { if (reflected != this) {
return reflected.toString(); return reflected.toString();
} }