Create PropertyDescriptorImpl under nonCancelableSection

PropertyDescriptorImpl initialization consists of two phases:
ctor + setType.
When PropertyDescriptorImpl is created wrapped descriptor
(e.g. WithDestructuringDeclaration) is leaked through bindingTrace
with not fully initialized `containingDeclaration` (that is
PropertyDescriptorImpl).
If PCE happens after this unsafe publication prior to `setType` then it
will be case with NPE on fully initialized instance reading.

#KT-56388 Fixed
This commit is contained in:
Vladimir Dolzhenko
2023-02-02 17:13:41 +01:00
committed by Space Team
parent e0dce31cde
commit 9be4aa2e02
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.resolve;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.intellij.openapi.diagnostic.ControlFlowException;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import kotlin.Pair; import kotlin.Pair;
@@ -315,6 +317,7 @@ public class DescriptorResolver {
@NotNull Annotations additionalAnnotations, @NotNull Annotations additionalAnnotations,
@Nullable InferenceSession inferenceSession @Nullable InferenceSession inferenceSession
) { ) {
try {
KotlinType varargElementType = null; KotlinType varargElementType = null;
KotlinType variableType = type; KotlinType variableType = type;
if (valueParameter.hasModifier(VARARG_KEYWORD)) { if (valueParameter.hasModifier(VARARG_KEYWORD)) {
@@ -391,6 +394,13 @@ public class DescriptorResolver {
trace.record(BindingContext.VALUE_PARAMETER, valueParameter, valueParameterDescriptor); trace.record(BindingContext.VALUE_PARAMETER, valueParameter, valueParameterDescriptor);
return valueParameterDescriptor; return valueParameterDescriptor;
} }
catch (Exception e) {
if (e instanceof ControlFlowException) {
throw new IllegalStateException("Method should be run under nonCancelableSection", e);
}
throw e;
}
}
@NotNull @NotNull
private Annotations resolveValueParameterAnnotations( private Annotations resolveValueParameterAnnotations(
@@ -913,6 +923,7 @@ public class DescriptorResolver {
annotationSplitter.getOtherAnnotations()) annotationSplitter.getOtherAnnotations())
); );
return ProgressManager.getInstance().computeInNonCancelableSection(() -> {
PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create( PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(
container, container,
propertyAnnotations, propertyAnnotations,
@@ -1055,6 +1066,7 @@ public class DescriptorResolver {
); );
trace.record(BindingContext.VARIABLE, variableDeclaration, propertyDescriptor); trace.record(BindingContext.VARIABLE, variableDeclaration, propertyDescriptor);
return propertyDescriptor; return propertyDescriptor;
});
} }
@NotNull @NotNull