Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KTOR-7479 Quick fix for compatibility with R8 full mode #4369

Merged
merged 4 commits into from
Oct 7, 2024

Conversation

osipxd
Copy link
Member

@osipxd osipxd commented Oct 4, 2024

Subsystem
Client/Server

Motivation
KTOR-7479 - createClientPlugin fails in runtime if an application is obfuscated with ProGuard/R8.

Solution
The problem occurs when typeOf is called with a generic type (ex. typeOf<List<T>> where T is specified in function or class signature).

  1. When a generic is a part of a function signature, the signature is saved during compilation to access it later on runtime. ProGuard/R8 breaks such calls as it changes names of functions and types.
  2. When a generic is a part of a class signature, typeOf relies on class attributes which are stripped if R8 is running in full mode.

The first problem is straightforward to solve, while the second one is tricky. As a quick solution, we just use a type without generics in case generics can't be retrieved from class attributes.

It is better to review commit-by-commit

@osipxd osipxd force-pushed the osipxd/createClientPlugin-obfuscation branch from a55d4c8 to 377d595 Compare October 4, 2024 15:08
Comment on lines +15 to +19
// kType != null always returns false, so we try to get javaType anyway
kType!!.javaType
} catch (_: NullPointerException) {
// Fallback to a type without generics if we can't get KType for the given T
T::class.java
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will create an issue in the Kotlin project and mention its number here

Comment on lines -52 to -53
object : ClientPlugin<PluginConfigT> {
override val key: AttributeKey<ClientPluginInstance<PluginConfigT>> = AttributeKey(name)
Copy link
Member Author

@osipxd osipxd Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the problems was here because. typeOf call on a generic type inside a non-inline function produces something like this:

KTypeParameter var10006 = Reflection.typeParameter(new FunctionReferenceImpl(3, CreatePluginUtilsKt.class, "createClientPlugin", "createClientPlugin(Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Lio/ktor/client/plugins/api/ClientPlugin;", 1), "PluginConfigT", KVariance.INVARIANT, false);

And it doesn't work after obfuscation.

@osipxd osipxd force-pushed the osipxd/createClientPlugin-obfuscation branch from 377d595 to 55a72a6 Compare October 4, 2024 15:51
@osipxd osipxd marked this pull request as ready for review October 4, 2024 15:51
@osipxd osipxd requested a review from bjhham October 4, 2024 16:22
Copy link
Contributor

@bjhham bjhham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, nice sleuthing 👍

@osipxd osipxd self-assigned this Oct 6, 2024
@osipxd osipxd force-pushed the osipxd/createClientPlugin-obfuscation branch from 8f73aae to 4127dcb Compare October 7, 2024 12:00
@osipxd osipxd merged commit 2097f34 into main Oct 7, 2024
9 of 14 checks passed
@osipxd osipxd deleted the osipxd/createClientPlugin-obfuscation branch October 7, 2024 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants