From 6a19e45e2760a14a22dab309fed2f53d229b8321 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Mon, 7 Jan 2019 16:46:22 +0100 Subject: [PATCH] Avoid ConcurrentModificationException #KT-26384 Fixed --- .../inline/CoveringTryCatchNodeProcessor.kt | 6 +- .../inline/InternalFinallyBlockInliner.java | 2 +- .../nonLocalReturns/tryFinally/kt26384.kt | 36 ++++++++++++ .../nonLocalReturns/tryFinally/kt26384_2.kt | 55 +++++++++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 10 ++++ ...otlinAgainstInlineKotlinTestGenerated.java | 10 ++++ .../IrBlackBoxInlineCodegenTestGenerated.java | 10 ++++ .../IrNonLocalReturnsTestGenerated.java | 10 ++++ .../NonLocalReturnsTestGenerated.java | 10 ++++ 9 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt create mode 100644 compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt index 977b9b985e9..6becd65da34 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt @@ -20,6 +20,8 @@ import com.google.common.collect.LinkedListMultimap import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful import org.jetbrains.org.objectweb.asm.tree.* import java.util.* +import kotlin.collections.HashSet +import kotlin.collections.LinkedHashSet abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) { val tryBlocksMetaInfo: IntervalMetaInfo = IntervalMetaInfo(this) @@ -114,7 +116,7 @@ class IntervalMetaInfo>(private val processor: Coverin } fun splitAndRemoveCurrentIntervals(by: Interval, keepStart: Boolean) { - currentIntervals.map { splitAndRemoveInterval(it, by, keepStart) } + currentIntervals.toList().forEach { splitAndRemoveIntervalFromCurrents(it, by, keepStart) } } fun processCurrent(curIns: LabelNode, directOrder: Boolean) { @@ -140,7 +142,7 @@ class IntervalMetaInfo>(private val processor: Coverin return split } - fun splitAndRemoveInterval(interval: T, by: Interval, keepStart: Boolean): SplitPair { + fun splitAndRemoveIntervalFromCurrents(interval: T, by: Interval, keepStart: Boolean): SplitPair { val splitPair = split(interval, by, keepStart) val removed = currentIntervals.remove(splitPair.patchedPart) assert(removed) { "Wrong interval structure: $splitPair" } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java index 34873255a30..5752c217379 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java @@ -391,7 +391,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor { // so we should split original interval by inserted finally one for (TryCatchBlockNodeInfo block : updatingClusterBlocks) { //update exception mapping - SplitPair split = tryBlocksMetaInfo.splitAndRemoveInterval(block, splitBy, false); + SplitPair split = tryBlocksMetaInfo.splitAndRemoveIntervalFromCurrents(block, splitBy, false); checkFinally(split.getNewPart()); checkFinally(split.getPatchedPart()); //block patched in split method diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt new file mode 100644 index 00000000000..95261119da1 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt @@ -0,0 +1,36 @@ +// IGNORE_BACKEND: JVM_IR +// NO_CHECK_LAMBDA_INLINING +// FILE: 1.kt + +package test + +public inline fun T.myapply(block: T.() -> Unit): T { + block() + return this +} + + +// FILE: 2.kt +import test.* + +class Test(val value: () -> String) { + fun test(): String { + try { + myapply { + try { + return value() + } catch (e: Exception) { + } catch (e: Throwable) { + } + } + } finally { + + } + + return "fail" + } +} + +fun box(): String { + return Test { "OK" }.test() +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt new file mode 100644 index 00000000000..586a0bb5ba2 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt @@ -0,0 +1,55 @@ +// IGNORE_BACKEND: JVM_IR +// NO_CHECK_LAMBDA_INLINING +// FILE: 1.kt + +package test + +public inline fun T.myapply(block: T.() -> Unit): T { + block() + return this +} + + +// FILE: 2.kt +import test.* +var globalResult = "" + +class Test(val value: () -> String) { + fun test(): String { + globalResult = "" + try { + myapply { + try { + return value() + } catch (e: Exception) { + globalResult += "Exception" + } catch (e: Throwable) { + globalResult += "Throwable" + } + } + } finally { + globalResult += " Finally" + } + + return globalResult + } +} + +fun box(): String { + Test { throw RuntimeException("123")}.test() + if (globalResult != "Exception Finally") { + return "fail 1: $globalResult" + } + + Test { throw Throwable("123") }.test() + if (globalResult != "Throwable Finally") { + return "fail 2: $globalResult" + } + + val result = Test { "OK" }.test() + + if (globalResult != " Finally") { + return "fail 3: $globalResult" + } + return result +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index 769b687342e..9764d369f02 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -2035,6 +2035,16 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt"); } + @TestMetadata("kt26384.kt") + public void testKt26384() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt"); + } + + @TestMetadata("kt26384_2.kt") + public void testKt26384_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt"); + } + @TestMetadata("kt6956.kt") public void testKt6956() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 1f842f4bb04..1fee28d3385 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -2035,6 +2035,16 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt"); } + @TestMetadata("kt26384.kt") + public void testKt26384() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt"); + } + + @TestMetadata("kt26384_2.kt") + public void testKt26384_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt"); + } + @TestMetadata("kt6956.kt") public void testKt6956() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java index ef242c35cb7..5a463ebdb58 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java @@ -2035,6 +2035,16 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt"); } + @TestMetadata("kt26384.kt") + public void testKt26384() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt"); + } + + @TestMetadata("kt26384_2.kt") + public void testKt26384_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt"); + } + @TestMetadata("kt6956.kt") public void testKt6956() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrNonLocalReturnsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrNonLocalReturnsTestGenerated.java index 582ab2b3be9..e7c38754ed2 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrNonLocalReturnsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrNonLocalReturnsTestGenerated.java @@ -149,6 +149,16 @@ public class IrNonLocalReturnsTestGenerated extends AbstractIrNonLocalReturnsTes runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt"); } + @TestMetadata("kt26384.kt") + public void testKt26384() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt"); + } + + @TestMetadata("kt26384_2.kt") + public void testKt26384_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt"); + } + @TestMetadata("kt6956.kt") public void testKt6956() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/NonLocalReturnsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/NonLocalReturnsTestGenerated.java index 7fdb46424fb..c4baaf7d628 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/NonLocalReturnsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/NonLocalReturnsTestGenerated.java @@ -149,6 +149,16 @@ public class NonLocalReturnsTestGenerated extends AbstractNonLocalReturnsTest { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt"); } + @TestMetadata("kt26384.kt") + public void testKt26384() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384.kt"); + } + + @TestMetadata("kt26384_2.kt") + public void testKt26384_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt"); + } + @TestMetadata("kt6956.kt") public void testKt6956() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt");