fix(rooms): guard room user moderation packets

This commit is contained in:
simoleo89
2026-06-15 22:15:39 +02:00
parent c48e01cb8e
commit 827b130ccc
4 changed files with 99 additions and 6 deletions
@@ -0,0 +1,39 @@
package com.eu.habbo.messages.incoming.rooms.users;
import org.junit.jupiter.api.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertTrue;
class RoomUserMuteGuardContractTest {
private static String source() throws Exception {
return Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserMuteEvent.java"));
}
@Test
void muteDurationIsBoundedBeforeApplyingMute() throws Exception {
String source = source();
int targetLookup = source.indexOf("Habbo habbo = room.getHabbo(userId)");
int durationGuard = source.indexOf("minutes < MIN_MUTE_MINUTES || minutes > MAX_MUTE_MINUTES", targetLookup);
int muteCall = source.indexOf("room.muteHabbo(habbo, minutes)", targetLookup);
assertTrue(targetLookup > -1, "Mute handler must resolve the room target");
assertTrue(durationGuard > targetLookup, "Mute handler must bound client-provided minutes");
assertTrue(durationGuard < muteCall, "Mute duration must be validated before mutating room state");
}
@Test
void unkickableTargetsCannotBeMutedThroughRoomPacket() throws Exception {
String source = source();
int unkickableGuard = source.indexOf("habbo.hasPermission(Permission.ACC_UNKICKABLE)");
int muteCall = source.indexOf("room.muteHabbo(habbo, minutes)");
assertTrue(unkickableGuard > -1, "Room mute must respect ACC_UNKICKABLE like kick and ban");
assertTrue(unkickableGuard < muteCall, "Unkickable targets must be rejected before muting");
}
}
@@ -0,0 +1,41 @@
package com.eu.habbo.messages.incoming.rooms.users;
import org.junit.jupiter.api.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertTrue;
class RoomUserSignGuardContractTest {
private static String source() throws Exception {
return Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/rooms/users/RoomUserSignEvent.java"));
}
@Test
void signIdIsValidatedBeforeRoomStateAndWiredTriggers() throws Exception {
String source = source();
int signRead = source.indexOf("int signId = this.packet.readInt()");
int guard = source.indexOf("signId < MIN_SIGN_ID || signId > MAX_SIGN_ID", signRead);
int status = source.indexOf("setStatus(RoomUnitStatus.SIGN", signRead);
int wired = source.indexOf("WiredManager.triggerUserPerformsAction", signRead);
assertTrue(signRead > -1, "Sign handler must read the client-provided sign id");
assertTrue(guard > signRead, "Sign handler must reject out-of-range sign ids");
assertTrue(guard < status, "Sign id must be validated before status mutation");
assertTrue(guard < wired, "Sign id must be validated before wired triggers");
}
@Test
void voteCountersOnlyReceiveValidatedSigns() throws Exception {
String source = source();
int guard = source.indexOf("signId < MIN_SIGN_ID || signId > MAX_SIGN_ID");
int vote = source.indexOf(".vote(room, userId, signId)");
assertTrue(guard > -1, "Sign id range guard must exist");
assertTrue(vote > guard, "Vote counters must only receive signs after the range guard");
}
}