fix(modtool): validate report payloads

This commit is contained in:
simoleo89
2026-06-15 20:01:34 +02:00
parent 8ba9132e7e
commit 044d1141cd
9 changed files with 196 additions and 11 deletions
@@ -0,0 +1,69 @@
package com.eu.habbo.messages.incoming.modtool;
import org.junit.jupiter.api.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ModToolReportInputContractTest {
@Test
void reportHandlersNormalizeAndBoundFreeText() throws Exception {
Path base = Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool");
for (String handler : List.of(
"ReportEvent.java",
"ReportFriendPrivateChatEvent.java",
"ReportCommentEvent.java",
"ReportThreadEvent.java"
)) {
String source = Files.readString(base.resolve(handler));
assertTrue(source.contains("ModToolReportInputGuard.normalize"),
handler + " must normalize report text before persistence or staff broadcast");
assertTrue(source.contains("ModToolReportInputGuard.isValidReportMessage"),
handler + " must reject empty or oversized report text");
}
}
@Test
void reportHandlersRejectInvalidIdsAndCounts() throws Exception {
Path base = Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool");
for (String handler : List.of(
"ReportEvent.java",
"ReportFriendPrivateChatEvent.java",
"ReportCommentEvent.java",
"ReportThreadEvent.java",
"ReportBullyEvent.java",
"ReportPhotoEvent.java"
)) {
String source = Files.readString(base.resolve(handler));
assertTrue(source.contains("ModToolReportInputGuard.isPositiveId"),
handler + " must reject zero or negative ids supplied by the client");
}
String privateChat = Files.readString(base.resolve("ReportFriendPrivateChatEvent.java"));
assertTrue(privateChat.contains("ModToolReportInputGuard.isValidPrivateChatLogCount(count)"),
"private chat reports must reject negative or oversized client-provided chatlog counts");
}
@Test
void reportEventValidatesTopicBeforeUsingReply() throws Exception {
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool/ReportEvent.java"));
assertTrue(source.indexOf("if (cfhTopic == null)") < source.indexOf("cfhTopic.reply"),
"ReportEvent must reject unknown topics before dereferencing the reply text");
}
@Test
void bullyReportUsesSameMutedUserGateAsNormalReports() throws Exception {
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/modtool/ReportBullyEvent.java"));
assertTrue(source.contains("if (!this.client.getHabbo().getHabboStats().allowTalk())"),
"bully reports must reject muted users instead of rejecting users who can talk");
}
}
@@ -0,0 +1,37 @@
package com.eu.habbo.messages.incoming.modtool;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ModToolReportInputGuardTest {
@Test
void normalizesNullableMessages() {
assertEquals("", ModToolReportInputGuard.normalize(null));
assertEquals("report", ModToolReportInputGuard.normalize(" report "));
}
@Test
void reportMessagesMustBeNonEmptyAndBounded() {
assertFalse(ModToolReportInputGuard.isValidReportMessage(""));
assertFalse(ModToolReportInputGuard.isValidReportMessage(null));
assertTrue(ModToolReportInputGuard.isValidReportMessage("a".repeat(ModToolReportInputGuard.MAX_REPORT_MESSAGE_LENGTH)));
assertFalse(ModToolReportInputGuard.isValidReportMessage("a".repeat(ModToolReportInputGuard.MAX_REPORT_MESSAGE_LENGTH + 1)));
}
@Test
void privateChatLogCountsAreBounded() {
assertFalse(ModToolReportInputGuard.isValidPrivateChatLogCount(0));
assertTrue(ModToolReportInputGuard.isValidPrivateChatLogCount(ModToolReportInputGuard.MAX_PRIVATE_CHAT_LOGS));
assertFalse(ModToolReportInputGuard.isValidPrivateChatLogCount(ModToolReportInputGuard.MAX_PRIVATE_CHAT_LOGS + 1));
}
@Test
void idsMustBePositive() {
assertFalse(ModToolReportInputGuard.isPositiveId(0));
assertFalse(ModToolReportInputGuard.isPositiveId(-1));
assertTrue(ModToolReportInputGuard.isPositiveId(1));
}
}