Skip to content

Overlong message chunk in secret stream push causes "double free or corruption" VM crash #81

@timmc

Description

@timmc

I was getting VM crashes after some code changes where I messed up buffer sizes, and I've narrowed it down to this simplified repro case (in Kotlin):

fun repro() {
    val sodium: LazySodiumJava by lazy { LazySodiumJava(SodiumJava()) }
    val STREAM_CHUNK_BYTES = 4000

    val key = (sodium as SecretStream.Lazy).cryptoSecretStreamKeygen()
    val stream = (sodium as SecretStream.Native)
    val state = SecretStream.State()
    val header = ByteArray(SecretStream.HEADERBYTES)
    stream.cryptoSecretStreamInitPush(state, header, key.asBytes)
    || throw IOException("error")
    val cipherChunk = ByteArray(STREAM_CHUNK_BYTES + SecretStream.ABYTES)

    // This triggers the bug
    val msgChunkTooBig = ByteArray(STREAM_CHUNK_BYTES + 2000)

    // Bad call
    stream.cryptoSecretStreamPush(
        state, cipherChunk,
        msgChunkTooBig, msgChunkTooBig.size.toLong(),
        SecretStream.TAG_MESSAGE
    ) || throw IOException("error")
}

It could probably be simplified more, but it looks like cryptoSecretStreamPush doesn't check byte array sizes before calling libsodium, and libsodium doesn't check either. I think what's going on is that if the message array is too large, libsodium ends up writing past the end of the cipher array and causing memory corruption. I suppose this is similar to issue #64.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions