Skip to content

PacketParser.decompressPayload spins at 100% CPU forever on malformed aMule EC packet #102

@janaxhell

Description

@janaxhell

Hello. Today I noticed by chance that Amarr was pushing my server CPU to 100% since almost a week. It was by chance, because it caused no visible problem. So I asked Claude Code to check. It fixed it, but said this problem of malformed chunks can happen again, so it suggested to open the following issue:

Describe the bug

The eventLoopGroupProxy-4-4 thread gets stuck in an infinite loop inside PacketParser.decompressPayload when aMule sends a malformed or corrupt compressed EC packet. The thread holds the socket lock indefinitely, eventually blocking all other worker threads and causing the application to freeze while consuming 100% of one CPU core.

To Reproduce

Difficult to reproduce deterministically — it appears to be triggered by a specific malformed response from the aMule EC API (observed after the aMule daemon had been running for several days with ~15 active downloads).

Expected behavior

decompressPayload should either:

enforce a maximum decompressed size limit (bomb protection), or
have a timeout / maximum iteration count, or
validate the packet header’s declared payload length before attempting decompression.
Actual behavior

Thread spins at 100% CPU indefinitely with no log output, no exception thrown, no watchdog recovery.

Thread dump (SIGQUIT / kill -3)

"eventLoopGroupProxy-4-4" #23 daemon prio=5 os_prio=0 cpu=278135477.97ms elapsed=324614.89s
   java.lang.Thread.State: RUNNABLE
        at jamule.ec.packet.PacketParser.decompressPayload-9vbjbqo(PacketParser.kt:94)
        at jamule.ec.packet.PacketParser.parseTransport(PacketParser.kt:40)
        at jamule.ec.packet.PacketParser.parse(PacketParser.kt:20)
        at jamule.AmuleConnection.sendRequestNoAuth(AmuleConnection.kt:73)
        - locked <0x000000060cdae600> (a java.net.Socket)

Other worker threads blocking as a consequence:

"eventLoopGroupProxy-4-3" #22  cpu=13260.96ms elapsed=324615.08s  waiting for monitor entry
Timeline
~2026-04-29 06:20: aMule sent the malformed packet, thread entered infinite loop
2026-05-02 09:15: last log entry (all other threads eventually blocked on socket lock)
2026-05-02 11:32: discovered — container had been at 100% CPU for ~4 days

Environment

Image: vexdev/amarr:latest
Java: OpenJDK 17.0.2
aMule version: 2.3.3 (EC API)
Host OS: Debian (Docker container on OpenMediaVault)
Workaround

docker restart amarr clears the stuck thread.

Suggested fix

In PacketParser.kt around line 94, add a decompressed size guard before or during the decompression loop:

// Example guard — reject if decompressed size exceeds reasonable limit (e.g. 50MB)
if (decompressedSize > MAX_PACKET_SIZE) {
    throw IOException("Packet decompressed size $decompressedSize exceeds limit")
}

Alternatively, wrap the decompression in a coroutine with withTimeout(...) so a hung decompression is recoverable without restarting the entire process.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions