Bypassing Kotlin’s Null-Safety

In this short article, we will have a look at how we can bypass Kotlin’s native null-safety with sun.misc.Unsafe, and see why it can be dangerous even if we are not messing up with it directly.

Mythical sun.misc.Unsafe

The sun.misc.Unsafe class is an internal JVM tool for executing low-level operations like off-heap memory allocation, thread parking, CAS, and much more.

This class is like one of those scary computer game creatures that are there only to intimidate us, in theory, we can’t get close because they are part of the environment, but it’s often possible by exploiting glitches or holes.

If we try to access the Unsafe instance, we encounter a private constructor and a static getUnsafe() method that raises a SecurityException practically every time we call it:

public final class Unsafe {
    private static final Unsafe theUnsafe;
    // ...

    private Unsafe() {}

    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }
}

 

So, in theory, it’s guarded by a strong encapsulation, and an exception being thrown on every getUnsafe() call… but we do have the Reflection mechanism, and we can easily bypass those:

private fun getUnsafe(): Unsafe {
    return Unsafe::class.java.getDeclaredField("theUnsafe")
            .apply { isAccessible = true }
            .let { it.get(null) as Unsafe }
}

Mighty Unsafe.allocateInstance()

This method allocates an empty instance of a given class directly on the heap ignoring field initialization and constructors.

And this allows us, indeed, to effectively bypass Kotlin’s safety checks:

A cool thing to do on Friday’s evening, but what about just not using Unsafe and staying (null)safe?

Problem: Unsafe in External Libraries

The problem is that most Java libraries were written with Java in mind, where using Unsafe for certain scenarios is slightly less unsafe than it is e.g., for Kotlin.

This is especially the case with serialization/deserialization libraries – one of such is Google’s Gson which internally uses Unsafe for instantiating objects in certain situations – which is totally acceptable for Java.

If we start using it in Kotlin, we indeed might end up with an undesired behaviour observed above:

@Test
fun unsafe_2() {
    val foo = Gson().fromJson("{}", Foo::class.java)

    assertThat(foo.nonNullable).isNull()
}

In this case, we simply need to perform checks manually after instantiation, which is not super problematic – what’s problematic is the lack of consciousness that this happens, which can cost much.

Are you sure the library you are using is not doing that internally?

Code snippets can be found on GitHub.

Key Takeaways

  • Kotlin’s null-safety does not go beyond objects’ initialization phase and is bypassable
  • External libraries that use Unsafe internally can do that too – it’s important to be aware of this
You May Also Like

Thought static method can’t be easy to mock, stub nor track? Wrong!

No matter why, no matter is it a good idea. Sometimes one just wants to check or it's necessary to be done. Mock a static method, woot? Impossibru!

In pure Java world it is still a struggle. But Groovy allows you to do that really simple. Well, not groovy alone, but with a great support of Spock.

Lets move on straight to the example. To catch some context we have an abstract for the example needs. A marketing project with a set of offers. One to many.

import spock.lang.Specification

class OfferFacadeSpec extends Specification {

    OfferFacade facade = new OfferFacade()

    def setup() {
        GroovyMock(Project, global: true)
    }

    def 'delegates an add offer call to the domain with proper params'() {
        given:
            Map params = [projId: projectId, name: offerName]

        when:
            Offer returnedOffer = facade.add(params)

        then:
            1 * Project.addOffer(projectId, _) >> { projId, offer -> offer }
            returnedOffer.name == params.name

        where:
            projectId | offerName
            1         | 'an Offer'
            15        | 'whasup!?'
            123       | 'doskonała oferta - kup teraz!'
    }
}
So we test a facade responsible for handling "add offer to the project" call triggered  somewhere in a GUI.
We want to ensure that static method Project.addOffer(long, Offer) will receive correct params when java.util.Map with user form input comes to the facade.add(params).
This is unit test, so how Project.addOffer() works is out of scope. Thus we want to stub it.

The most important is a GroovyMock(Project, global: true) statement.
What it does is modifing Project class to behave like a Spock's mock. 
GroovyMock() itself is a method inherited from SpecificationThe global flag is necessary to enable mocking static methods.
However when one comes to the need of mocking static method, author of Spock Framework advice to consider redesigning of implementation. It's not a bad advice, I must say.

Another important thing are assertions at then: block. First one checks an interaction, if the Project.addOffer() method was called exactly once, with a 1st argument equal to the projectId and some other param (we don't have an object instance yet to assert anything about it).
Right shit operator leads us to the stub which replaces original method implementation by such statement.
As a good stub it does nothing. The original method definition has return type Offer. The stub needs to do the same. So an offer passed as the 2nd argument is just returned.
Thanks to this we can assert about name property if it's equal with the value from params. If no return was designed the name could be checked inside the stub Closure, prefixed with an assert keyword.

Worth of  mentioning is that if you want to track interactions of original static method implementation without replacing it, then you should try using GroovySpy instead of GroovyMock.

Unfortunately static methods declared at Java object can't be treated in such ways. Though regular mocks and whole goodness of Spock can be used to test pure Java code, which is awesome anyway :)No matter why, no matter is it a good idea. Sometimes one just wants to check or it's necessary to be done. Mock a static method, woot? Impossibru!

In pure Java world it is still a struggle. But Groovy allows you to do that really simple. Well, not groovy alone, but with a great support of Spock.

Lets move on straight to the example. To catch some context we have an abstract for the example needs. A marketing project with a set of offers. One to many.

import spock.lang.Specification

class OfferFacadeSpec extends Specification {

    OfferFacade facade = new OfferFacade()

    def setup() {
        GroovyMock(Project, global: true)
    }

    def 'delegates an add offer call to the domain with proper params'() {
        given:
            Map params = [projId: projectId, name: offerName]

        when:
            Offer returnedOffer = facade.add(params)

        then:
            1 * Project.addOffer(projectId, _) >> { projId, offer -> offer }
            returnedOffer.name == params.name

        where:
            projectId | offerName
            1         | 'an Offer'
            15        | 'whasup!?'
            123       | 'doskonała oferta - kup teraz!'
    }
}
So we test a facade responsible for handling "add offer to the project" call triggered  somewhere in a GUI.
We want to ensure that static method Project.addOffer(long, Offer) will receive correct params when java.util.Map with user form input comes to the facade.add(params).
This is unit test, so how Project.addOffer() works is out of scope. Thus we want to stub it.

The most important is a GroovyMock(Project, global: true) statement.
What it does is modifing Project class to behave like a Spock's mock. 
GroovyMock() itself is a method inherited from SpecificationThe global flag is necessary to enable mocking static methods.
However when one comes to the need of mocking static method, author of Spock Framework advice to consider redesigning of implementation. It's not a bad advice, I must say.

Another important thing are assertions at then: block. First one checks an interaction, if the Project.addOffer() method was called exactly once, with a 1st argument equal to the projectId and some other param (we don't have an object instance yet to assert anything about it).
Right shit operator leads us to the stub which replaces original method implementation by such statement.
As a good stub it does nothing. The original method definition has return type Offer. The stub needs to do the same. So an offer passed as the 2nd argument is just returned.
Thanks to this we can assert about name property if it's equal with the value from params. If no return was designed the name could be checked inside the stub Closure, prefixed with an assert keyword.

Worth of  mentioning is that if you want to track interactions of original static method implementation without replacing it, then you should try using GroovySpy instead of GroovyMock.

Unfortunately static methods declared at Java object can't be treated in such ways. Though regular mocks and whole goodness of Spock can be used to test pure Java code, which is awesome anyway :)

Touki na Confiturze 2013 – ciąg dalszy

Kolejna partia nagrań z konferencji została udostępniona. Wśród nich m.in. prezentacja Michała Trzaskowskiego o rozpoznawaniu oczekiwań klienta podczas prowadzenia projektu z wykorzystaniem ”zwinnych” metodyk projektowych oraz wystąpienie Macieja Próchniaka o możliwościach Slick, jednej z bibliotek w Scali.