diff --git a/cache/src/main/kotlin/org/openrs2/cache/Js5Compression.kt b/cache/src/main/kotlin/org/openrs2/cache/Js5Compression.kt index 69c4422c..cbf4705a 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 321d4362..95e40832 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 00000000..593f4708 Binary files /dev/null and b/cache/src/test/resources/org/openrs2/cache/compression/missing-header.dat differ