Kotlin is not optimizing away unreachable code based on const vals


#1

Just created bug KT-17007 but thought that it was important to also alert other users of Kotlin as this could have serious security implications if you were relying on code being removed at compile time

Was playing around with trying to create some inline methods for some logging and having the code optimized away at compile time and discovered that unlike Java, Kotlin is not optimizing code away at compile time.

Consider this code:

const val doIt = false

fun baz()
{
    if(doIt) println("Hello")
}

Kotlin is generating all of the code for this method:

 public final static baz()V
   L0
    LINENUMBER 112 L0
    ICONST_0
    IFEQ L1
    LDC "Hello"
    ASTORE 0
   L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L3
   L4
   L1
    LINENUMBER 113 L1
    RETURN
   L5
    MAXSTACK = 2
    MAXLOCALS = 1

The equivalent code in Java:

public static final boolean doIt = false;

public void test()
{
    if(doIt) System.out.println("Hello");
}

produces a method with no code since the code can be eliminated.

This has major implications on several different fronts:

  • Code Size - code is emitted that can never be reached

  • Performance - code will get executed to check conditions that can never change

  • Security - Developers may have code for testing that is meant to be compiled out based on a constant so that test code is not available to end users. Shipping that code in the classes could expose secret information.

If the condition inside the if is changed to the literal constant false then the code is optimized away, but not based on a constant.