kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

IllegalArgumentException due to PrimitiveSerialDescriptor serialName clashes

Open MarioNoll opened this issue 3 years ago • 2 comments

Describe the bug After upgrading to 1.4.0 I was seeing runtime crashes originating here https://github.com/Kotlin/kotlinx.serialization/blob/v1.4.0/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt#L66

Amongst others we have a custom serializer for DayOfWeek:

@Serializer(forClass = DayOfWeek::class)
public object DayOfWeekSerializer : KSerializer<DayOfWeek> {

  override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(javaClass.simpleName, PrimitiveKind.STRING)
  ...

Running r8 the obfuscated javaClass.simpleName for DayOfWeekSerializer resulted in being a. In comparison the obfuscated class names of the built in serializers looked like this:

 Obfuscated classname of "Char":          Char
 Obfuscated classname of "CharArray":     CharArray
 Obfuscated classname of "Double":        Double
 Obfuscated classname of "DoubleArray":   DoubleArray
 Obfuscated classname of "Float":         Float
 Obfuscated classname of "FloatArray":    FloatArray
 Obfuscated classname of "Long":          Long
 Obfuscated classname of "LongArray":     LongArray
 Obfuscated classname of "Int":           Int
 Obfuscated classname of "IntArray":      IntArray
 Obfuscated classname of "Short":         Short
 Obfuscated classname of "ShortArray":    ShortArray
 Obfuscated classname of "Byte":          Byte
 Obfuscated classname of "ByteArray":     ByteArray
 Obfuscated classname of "Boolean":       Boolean
 Obfuscated classname of "BooleanArray":  BooleanArray
 Obfuscated classname of "Unit":          t
 Obfuscated classname of "Duration":      a

Due to the Duration (added in https://github.com/Kotlin/kotlinx.serialization/pull/1960), being obfuscated to a as well this crashed. For now I fixed this with a proguard rule which keeps the class names of the serializers:

-keepnames class ** extends kotlinx.serialization.KSerializer

Expected behavior I would have expected that the class names of the built in serializers (Unit and Duration) are not obfuscated, or to have this handled by the recommended proguard rules for Android. Maybe it is also not recommended to rely on javaClass.simpleName for the serialName?

Environment

  • Kotlin version: 1.7.10
  • Library version: 1.4.0
  • Kotlin platforms: JVM
  • Gradle version: 7.5.1

MarioNoll avatar Aug 29 '22 13:08 MarioNoll

I'm not sure it's possible to control the obfuscation pattern on our side, but we'll check if there are any specific rules.

javaClass.simpleName unfortunately is not an option because the core module is multiplatform.

sandwwraith avatar Aug 29 '22 14:08 sandwwraith

What I don't understand is that the Duration already has it's full pacakge name hardcoded in it's descriptor. I assume that the descriptor names must be unique?

https://github.com/Kotlin/kotlinx.serialization/blob/d5bc32dc11d2a8a08c36663b93839d4fe91f4507/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt#L16

PaulWoitaschek avatar Aug 30 '22 08:08 PaulWoitaschek