Merge pull request #215 from simoleo89/fix/network-rcon-safety

fix(rcon): bound inbound payload handling
This commit is contained in:
DuckieTM
2026-06-17 09:44:38 +02:00
committed by GitHub
3 changed files with 79 additions and 8 deletions
@@ -50,6 +50,30 @@ class RCONServerHandlerContractTest {
assertTrue(registerIndex < serverIndex, "RCON rate limit defaults must be registered before RCONServer is constructed");
}
@Test
void rconPayloadSizeIsBoundedBeforeBufferCopy() throws Exception {
String handler = handlerSource();
String emulator = emulatorSource();
int readableBytes = handler.indexOf("int readableBytes = data.readableBytes()");
int maxPayload = handler.indexOf("int maxPayloadBytes = maxPayloadBytes()", readableBytes);
int oversizedGuard = handler.indexOf("readableBytes > maxPayloadBytes", maxPayload);
int byteArray = handler.indexOf("new byte[readableBytes]", readableBytes);
assertTrue(handler.contains("DEFAULT_MAX_PAYLOAD_BYTES = 64 * 1024"),
"RCON handler should have a conservative default payload cap");
assertTrue(handler.contains("rcon.max_payload_bytes"),
"RCON max payload should be configurable");
assertTrue(readableBytes > -1, "RCON handler must read ByteBuf size before allocation");
assertTrue(maxPayload > readableBytes, "RCON handler must resolve max payload before allocation");
assertTrue(oversizedGuard > maxPayload, "RCON handler must reject oversized payloads");
assertTrue(oversizedGuard < byteArray, "Oversized RCON payloads must be rejected before byte array allocation");
assertTrue(handler.contains("PAYLOAD_TOO_LARGE"),
"RCON callers need a deterministic response for oversized payloads");
assertTrue(emulator.contains("register(\"rcon.max_payload_bytes\", \"65536\")"),
"RCON max payload default must be registered before startup");
}
@Test
void inboundByteBufIsReleasedFromFinallyBlock() throws Exception {
String source = handlerSource();
@@ -59,4 +83,16 @@ class RCONServerHandlerContractTest {
assertTrue(finallyIndex >= 0, "RCON channelRead must release inbound ByteBufs from a finally block");
assertTrue(releaseIndex > finallyIndex, "RCON channelRead must release the inbound ByteBuf after finally starts");
}
@Test
void rconWhitelistUsesSocketAddressInsteadOfStringSplitting() throws Exception {
String source = handlerSource();
assertTrue(source.contains("InetSocketAddress"),
"RCON whitelist should resolve socket addresses instead of parsing remoteAddress.toString()");
assertTrue(source.contains("getHostAddress()"),
"RCON whitelist should compare the resolved host address");
assertTrue(!source.contains(".toString().split(\":\")"),
"RCON whitelist must not split host:port strings because that breaks IPv6 addresses");
}
}