From 04e587cf1852a021f2799dd6f5ca022d3c017fd5 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Thu, 12 Dec 2019 11:04:51 +0300 Subject: [PATCH] Make sure that exception recovery does not break exception message Fixes #1631 --- .../jvm/src/internal/StackTraceRecovery.kt | 5 +++-- .../jvm/test/exceptions/StackTraceRecoveryTest.kt | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt index 727d934136..b512815556 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt @@ -66,14 +66,15 @@ private fun recoverFromStackFrame(exception: E, continuation: Co // Try to create an exception of the same type and get stacktrace from continuation val newException = tryCopyException(cause) ?: return exception + // Verify that the new exception has the same message as the original one (bail out if not, see #1631) + if (newException.message != cause.message) return exception + // Update stacktrace val stacktrace = createStackTrace(continuation) if (stacktrace.isEmpty()) return exception - // Merge if necessary if (cause !== exception) { mergeRecoveredTraces(recoveredStacktrace, stacktrace) } - // Take recovered stacktrace, merge it with existing one if necessary and return return createFinalException(cause, newException, stacktrace) } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt index de93708453..dbbd77c4b7 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt @@ -8,6 +8,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.channels.* import kotlinx.coroutines.intrinsics.* import org.junit.Test +import java.lang.RuntimeException import java.util.concurrent.* import kotlin.concurrent.* import kotlin.coroutines.* @@ -264,4 +265,18 @@ class StackTraceRecoveryTest : TestBase() { } yield() // nop to make sure it is not a tail call } + + @Test + fun testWrongMessageException() = runTest { + val result = runCatching { + coroutineScope { + throw WrongMessageException("OK") + } + } + val ex = result.exceptionOrNull() ?: error("Expected to fail") + assertTrue(ex is WrongMessageException) + assertEquals("Token OK", ex.message) + } + + public class WrongMessageException(token: String) : RuntimeException("Token $token") }