From 1a78ef3c7d4aecb928b9409975bdb36ab36e0bb9 Mon Sep 17 00:00:00 2001 From: Graham Date: Sun, 20 Mar 2022 21:30:23 +0000 Subject: [PATCH] Throw an exception if header is truncated Signed-off-by: Graham --- .../org/openrs2/cache/Js5Compression.kt | 12 ++++++++ .../org/openrs2/cache/Js5CompressionTest.kt | 27 ++++++++++++++++++ .../cache/compression/missing-header.dat | Bin 0 -> 4 bytes 3 files changed, 39 insertions(+) create mode 100644 cache/src/test/resources/org/openrs2/cache/compression/missing-header.dat diff --git a/cache/src/main/kotlin/org/openrs2/cache/Js5Compression.kt b/cache/src/main/kotlin/org/openrs2/cache/Js5Compression.kt index 69c4422c62..cbf4705a93 100644 --- a/cache/src/main/kotlin/org/openrs2/cache/Js5Compression.kt +++ b/cache/src/main/kotlin/org/openrs2/cache/Js5Compression.kt @@ -108,6 +108,10 @@ public object Js5Compression { } public fun uncompress(input: ByteBuf, key: XteaKey = XteaKey.ZERO): ByteBuf { + if (input.readableBytes() < 5) { + throw IOException("Missing header") + } + val typeId = input.readUnsignedByte().toInt() val type = Js5CompressionType.fromOrdinal(typeId) ?: throw IOException("Invalid compression type: $typeId") @@ -167,6 +171,10 @@ public object Js5Compression { } public fun uncompressIfKeyValid(input: ByteBuf, key: XteaKey): ByteBuf? { + if (input.readableBytes() < 5) { + throw IOException("Missing header") + } + val typeId = input.readUnsignedByte().toInt() val type = Js5CompressionType.fromOrdinal(typeId) ?: throw IOException("Invalid compression type: $typeId") @@ -358,6 +366,10 @@ public object Js5Compression { } public fun isEmptyLoc(buf: ByteBuf): Boolean { + if (buf.readableBytes() < 5) { + throw IOException("Missing header") + } + val typeId = buf.readUnsignedByte().toInt() val type = Js5CompressionType.fromOrdinal(typeId) ?: throw IOException("Invalid compression type: $typeId") diff --git a/cache/src/test/kotlin/org/openrs2/cache/Js5CompressionTest.kt b/cache/src/test/kotlin/org/openrs2/cache/Js5CompressionTest.kt index 321d4362e5..95e4083250 100644 --- a/cache/src/test/kotlin/org/openrs2/cache/Js5CompressionTest.kt +++ b/cache/src/test/kotlin/org/openrs2/cache/Js5CompressionTest.kt @@ -703,6 +703,33 @@ class Js5CompressionTest { } } + @Test + fun testMissingHeader() { + read("missing-header.dat").use { compressed -> + assertFailsWith { + Js5Compression.uncompress(compressed) + } + } + + read("missing-header.dat").use { compressed -> + assertFailsWith { + Js5Compression.uncompressUnlessEncrypted(compressed) + } + } + + read("missing-header.dat").use { compressed -> + assertFailsWith { + Js5Compression.uncompressIfKeyValid(compressed, XteaKey.ZERO) + } + } + + read("missing-header.dat").use { compressed -> + assertFailsWith { + Js5Compression.isEmptyLoc(compressed) + } + } + } + private fun read(name: String): ByteBuf { Js5CompressionTest::class.java.getResourceAsStream("compression/$name").use { input -> return Unpooled.wrappedBuffer(input.readBytes()) diff --git a/cache/src/test/resources/org/openrs2/cache/compression/missing-header.dat b/cache/src/test/resources/org/openrs2/cache/compression/missing-header.dat new file mode 100644 index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 GIT binary patch literal 4 LcmZQzU|;|M00aO5 literal 0 HcmV?d00001