You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-20 07:26:18 +00:00
Merge pull request #223 from simoleo89/fix/guild-badge-guards
fix(guilds): bound guild management inputs
This commit is contained in:
+59
@@ -0,0 +1,59 @@
|
||||
package com.eu.habbo.messages.incoming.guilds;
|
||||
|
||||
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 GuildManagementInputGuardContractTest {
|
||||
private static String source(String file) throws Exception {
|
||||
return Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/guilds/" + file));
|
||||
}
|
||||
|
||||
@Test
|
||||
void guildCreateAndRenameShareNameAndDescriptionBounds() throws Exception {
|
||||
String limits = source("GuildInputLimits.java");
|
||||
String buy = source("RequestGuildBuyEvent.java");
|
||||
String rename = source("GuildChangeNameDescEvent.java");
|
||||
|
||||
assertTrue(limits.contains("MAX_GUILD_NAME_LENGTH = 29"),
|
||||
"Guild names should keep the existing 29 character protocol bound");
|
||||
assertTrue(limits.contains("MAX_GUILD_DESCRIPTION_LENGTH = 254"),
|
||||
"Guild descriptions should keep the existing database/protocol bound");
|
||||
assertTrue(limits.contains("!name.isBlank()"),
|
||||
"Guild names must not be empty or whitespace-only");
|
||||
assertTrue(buy.contains("GuildInputLimits.isValidGuildName(name)"),
|
||||
"Guild purchase should use the shared name guard");
|
||||
assertTrue(buy.contains("GuildInputLimits.isValidGuildDescription(description)"),
|
||||
"Guild purchase should use the shared description guard");
|
||||
assertTrue(rename.contains("GuildInputLimits.isValidGuildName(newName)"),
|
||||
"Guild rename should reject invalid client names before plugin events");
|
||||
assertTrue(rename.contains("GuildInputLimits.isValidGuildName(nameEvent.name)"),
|
||||
"Guild rename should reject invalid plugin-mutated names before persistence");
|
||||
}
|
||||
|
||||
@Test
|
||||
void guildColorInputsAreCheckedAgainstLoadedPalette() throws Exception {
|
||||
String buy = source("RequestGuildBuyEvent.java");
|
||||
String colors = source("GuildChangeColorsEvent.java");
|
||||
|
||||
assertTrue(buy.contains("symbolColor(colorOne)") && buy.contains("backgroundColor(colorTwo)"),
|
||||
"Guild purchase should reject color ids that are not in the loaded guild palette");
|
||||
assertTrue(colors.contains("symbolColor(colorOne)") && colors.contains("backgroundColor(colorTwo)"),
|
||||
"Guild color changes should reject invalid client color ids");
|
||||
assertTrue(colors.contains("symbolColor(colorsEvent.colorOne)") && colors.contains("backgroundColor(colorsEvent.colorTwo)"),
|
||||
"Guild color changes should reject invalid plugin-mutated color ids");
|
||||
}
|
||||
|
||||
@Test
|
||||
void guildStateInputsStayInsideKnownEnumRange() throws Exception {
|
||||
String settings = source("GuildChangeSettingsEvent.java");
|
||||
|
||||
assertTrue(settings.contains("state < 0 || state >= GuildState.values().length"),
|
||||
"Guild settings should reject invalid client state ids before event dispatch");
|
||||
assertTrue(settings.contains("settingsEvent.state < 0 || settingsEvent.state >= GuildState.values().length"),
|
||||
"Guild settings should reject invalid plugin-mutated state ids before applying them");
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.eu.habbo.messages.incoming.guilds;
|
||||
|
||||
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 GuildMembersInputGuardContractTest {
|
||||
private static String eventSource() throws Exception {
|
||||
return Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/guilds/RequestGuildMembersEvent.java"));
|
||||
}
|
||||
|
||||
private static String managerSource() throws Exception {
|
||||
return Files.readString(Path.of("src/main/java/com/eu/habbo/habbohotel/guilds/GuildManager.java"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void guildMemberListInputsAreBoundedBeforeManagerQueries() throws Exception {
|
||||
String source = eventSource();
|
||||
|
||||
int pageRead = source.indexOf("int pageId = this.packet.readInt()");
|
||||
int queryRead = source.indexOf("String query = this.packet.readString()", pageRead);
|
||||
int levelRead = source.indexOf("int levelId = this.packet.readInt()", queryRead);
|
||||
int guard = source.indexOf("pageId < 0 || pageId > MAX_PAGE_ID", levelRead);
|
||||
int managerCall = source.indexOf("getGuildMembers(g, pageId, levelId, query)", guard);
|
||||
|
||||
assertTrue(source.contains("MAX_PAGE_ID = 1000"),
|
||||
"Guild member pagination should have a server-side upper bound");
|
||||
assertTrue(source.contains("MAX_QUERY_LENGTH = 32"),
|
||||
"Guild member search query should have a server-side length bound");
|
||||
assertTrue(source.contains("MAX_LEVEL_ID = 2"),
|
||||
"Guild member rank filter should be bounded to known levels");
|
||||
assertTrue(pageRead > -1 && queryRead > pageRead && levelRead > queryRead,
|
||||
"Guild member handler must read page/query/level from the packet");
|
||||
assertTrue(guard > levelRead && guard < managerCall,
|
||||
"Guild member handler must validate inputs before querying the manager");
|
||||
}
|
||||
|
||||
@Test
|
||||
void guildMemberCountEscapesLikeQuerySameAsListQuery() throws Exception {
|
||||
String source = managerSource();
|
||||
|
||||
int listMethod = source.indexOf("public ArrayList<GuildMember> getGuildMembers(Guild guild, int page, int levelId, String query)");
|
||||
int listEscape = source.indexOf("SqlLikeEscaper.escape(query)", listMethod);
|
||||
int countMethod = source.indexOf("public int getGuildMembersCount(Guild guild, int page, int levelId, String query)");
|
||||
int countEscape = source.indexOf("SqlLikeEscaper.escape(query)", countMethod);
|
||||
|
||||
assertTrue(listEscape > listMethod,
|
||||
"Guild member list query should escape SQL LIKE wildcards");
|
||||
assertTrue(countEscape > countMethod,
|
||||
"Guild member count query should escape SQL LIKE wildcards too");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user