diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableAgeMatch.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableAgeMatch.java index 18456674..15012809 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableAgeMatch.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableAgeMatch.java @@ -35,6 +35,7 @@ public class WiredConditionVariableAgeMatch extends WiredConditionHasVariable { private static final int DURATION_UNIT_WEEKS = 5; private static final int DURATION_UNIT_MONTHS = 6; private static final int DURATION_UNIT_YEARS = 7; + static final int MAX_DURATION_AMOUNT = 1_000_000; protected int compareValue = COMPARE_VALUE_CREATED; protected int comparison = COMPARISON_LOWER_THAN; @@ -97,7 +98,7 @@ public class WiredConditionVariableAgeMatch extends WiredConditionHasVariable { this.targetType = (params.length > 0) ? normalizeTargetTypeExtended(params[0]) : TARGET_USER; this.compareValue = (params.length > 1) ? normalizeCompareValue(params[1]) : COMPARE_VALUE_CREATED; this.comparison = (params.length > 2) ? normalizeComparison(params[2]) : COMPARISON_LOWER_THAN; - this.durationAmount = Math.max(0, (params.length > 3) ? params[3] : 0); + this.durationAmount = normalizeDurationAmount((params.length > 3) ? params[3] : 0); this.durationUnit = (params.length > 4) ? normalizeDurationUnit(params[4]) : DURATION_UNIT_SECONDS; this.userSource = (params.length > 5) ? normalizeUserSource(params[5]) : WiredSourceUtil.SOURCE_TRIGGER; this.furniSource = (params.length > 6) ? normalizeFurniSource(params[6]) : WiredSourceUtil.SOURCE_TRIGGER; @@ -130,6 +131,10 @@ public class WiredConditionVariableAgeMatch extends WiredConditionHasVariable { @Override public boolean evaluate(WiredContext ctx) { + if (ctx == null) { + return false; + } + Room room = ctx.room(); if (room == null || this.variableToken == null || this.variableToken.isEmpty() || !isCustomVariableToken(this.variableToken)) { @@ -192,7 +197,7 @@ public class WiredConditionVariableAgeMatch extends WiredConditionHasVariable { this.targetType = normalizeTargetTypeExtended(data.targetType); this.compareValue = normalizeCompareValue(data.compareValue); this.comparison = normalizeComparison(data.comparison); - this.durationAmount = Math.max(0, data.durationAmount); + this.durationAmount = normalizeDurationAmount(data.durationAmount); this.durationUnit = normalizeDurationUnit(data.durationUnit); this.userSource = normalizeUserSource(data.userSource); this.furniSource = normalizeFurniSource(data.furniSource); @@ -345,8 +350,8 @@ public class WiredConditionVariableAgeMatch extends WiredConditionHasVariable { return Math.max(0L, System.currentTimeMillis() - timestampMs); } - private static long durationToMillis(int amount, int unit) { - long normalizedAmount = Math.max(0L, amount); + static long durationToMillis(int amount, int unit) { + long normalizedAmount = normalizeDurationAmount(amount); return switch (unit) { case DURATION_UNIT_MILLISECONDS -> normalizedAmount; @@ -367,22 +372,26 @@ public class WiredConditionVariableAgeMatch extends WiredConditionHasVariable { return left * right; } - private static int normalizeTargetTypeExtended(int value) { + static int normalizeDurationAmount(int value) { + return Math.max(0, Math.min(MAX_DURATION_AMOUNT, value)); + } + + static int normalizeTargetTypeExtended(int value) { return switch (value) { case TARGET_FURNI, TARGET_CONTEXT, TARGET_ROOM -> value; default -> TARGET_USER; }; } - private static int normalizeCompareValue(int value) { + static int normalizeCompareValue(int value) { return (value == COMPARE_VALUE_UPDATED) ? COMPARE_VALUE_UPDATED : COMPARE_VALUE_CREATED; } - private static int normalizeComparison(int value) { + static int normalizeComparison(int value) { return (value == COMPARISON_HIGHER_THAN) ? COMPARISON_HIGHER_THAN : COMPARISON_LOWER_THAN; } - private static int normalizeDurationUnit(int value) { + static int normalizeDurationUnit(int value) { return switch (value) { case DURATION_UNIT_MILLISECONDS, DURATION_UNIT_SECONDS, DURATION_UNIT_MINUTES, DURATION_UNIT_HOURS, DURATION_UNIT_DAYS, DURATION_UNIT_WEEKS, DURATION_UNIT_MONTHS, DURATION_UNIT_YEARS -> value; diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableValueMatch.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableValueMatch.java index 13f79233..eb40e973 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableValueMatch.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariableValueMatch.java @@ -51,6 +51,7 @@ public class WiredConditionVariableValueMatch extends WiredConditionHasVariable private static final int COMPARISON_NOT_EQUAL = 5; private static final String DELIM = "\t"; private static final String FURNI_DELIM = ";"; + static final int MAX_ABS_REFERENCE_CONSTANT = 1_000_000_000; protected int comparison = COMPARISON_EQUAL; protected int referenceMode = REFERENCE_CONSTANT; @@ -123,7 +124,7 @@ public class WiredConditionVariableValueMatch extends WiredConditionHasVariable int nextTargetType = normalizeTargetTypeExtended(param(params, 0, TARGET_USER)); int nextComparison = normalizeComparison(param(params, 1, COMPARISON_EQUAL)); int nextReferenceMode = normalizeReferenceMode(param(params, 2, REFERENCE_CONSTANT)); - int nextReferenceConstantValue = param(params, 3, 0); + int nextReferenceConstantValue = normalizeReferenceConstantValue(param(params, 3, 0)); int nextReferenceTargetType = normalizeTargetTypeExtended(param(params, 4, TARGET_USER)); int nextUserSource = normalizeUserSource(param(params, 5, WiredSourceUtil.SOURCE_TRIGGER)); int nextFurniSource = normalizeFurniSource(param(params, 6, WiredSourceUtil.SOURCE_TRIGGER)); @@ -168,6 +169,10 @@ public class WiredConditionVariableValueMatch extends WiredConditionHasVariable @Override public boolean evaluate(WiredContext ctx) { + if (ctx == null) { + return false; + } + Room room = ctx.room(); if (room == null || this.variableToken == null || this.variableToken.isEmpty()) { @@ -220,14 +225,21 @@ public class WiredConditionVariableValueMatch extends WiredConditionHasVariable String wiredData = set.getString("wired_data"); if (wiredData == null || wiredData.isEmpty() || !wiredData.startsWith("{")) return; - JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); + JsonData data; + try { + data = WiredManager.getGson().fromJson(wiredData, JsonData.class); + } catch (RuntimeException exception) { + this.onPickUp(); + return; + } + if (data == null) return; this.targetType = normalizeTargetTypeExtended(data.targetType); this.setVariableToken(normalizeVariableToken((data.variableToken != null) ? data.variableToken : ((data.variableItemId > 0) ? String.valueOf(data.variableItemId) : ""))); this.comparison = normalizeComparison(data.comparison); this.referenceMode = normalizeReferenceMode(data.referenceMode); - this.referenceConstantValue = data.referenceConstantValue; + this.referenceConstantValue = normalizeReferenceConstantValue(data.referenceConstantValue); this.referenceTargetType = normalizeTargetTypeExtended(data.referenceTargetType); this.setReferenceVariableToken(normalizeVariableToken((data.referenceVariableToken != null) ? data.referenceVariableToken : ((data.referenceVariableItemId > 0) ? String.valueOf(data.referenceVariableItemId) : ""))); this.userSource = normalizeUserSource(data.userSource); @@ -737,32 +749,36 @@ public class WiredConditionVariableValueMatch extends WiredConditionHasVariable return (params.length > index) ? params[index] : fallback; } - private static int normalizeTargetTypeExtended(int value) { + static int normalizeTargetTypeExtended(int value) { return switch (value) { case TARGET_FURNI, TARGET_CONTEXT, TARGET_ROOM -> value; default -> TARGET_USER; }; } - private static int normalizeReferenceMode(int value) { + static int normalizeReferenceMode(int value) { return (value == REFERENCE_VARIABLE) ? REFERENCE_VARIABLE : REFERENCE_CONSTANT; } - private static int normalizeReferenceFurniSource(int value) { + static int normalizeReferenceFurniSource(int value) { return switch (value) { case SOURCE_SECONDARY_SELECTED, WiredSourceUtil.SOURCE_SELECTOR, WiredSourceUtil.SOURCE_SIGNAL -> value; default -> WiredSourceUtil.SOURCE_TRIGGER; }; } - private static int normalizeComparison(int value) { + static int normalizeComparison(int value) { return switch (value) { case COMPARISON_GREATER_THAN, COMPARISON_GREATER_THAN_OR_EQUAL, COMPARISON_LESS_THAN_OR_EQUAL, COMPARISON_LESS_THAN, COMPARISON_NOT_EQUAL -> value; default -> COMPARISON_EQUAL; }; } - private static int parseInteger(String value) { + static int normalizeReferenceConstantValue(int value) { + return Math.max(-MAX_ABS_REFERENCE_CONSTANT, Math.min(MAX_ABS_REFERENCE_CONSTANT, value)); + } + + static int parseInteger(String value) { try { return (value == null || value.trim().isEmpty()) ? 0 : Integer.parseInt(value.trim()); } catch (NumberFormatException e) { diff --git a/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariablePayloadGuardTest.java b/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariablePayloadGuardTest.java new file mode 100644 index 00000000..eaecc7f3 --- /dev/null +++ b/Emulator/src/test/java/com/eu/habbo/habbohotel/items/interactions/wired/conditions/WiredConditionVariablePayloadGuardTest.java @@ -0,0 +1,45 @@ +package com.eu.habbo.habbohotel.items.interactions.wired.conditions; + +import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class WiredConditionVariablePayloadGuardTest { + @Test + void variableAgeDurationsAreBounded() { + assertEquals(0, WiredConditionVariableAgeMatch.normalizeDurationAmount(-1)); + assertEquals(42, WiredConditionVariableAgeMatch.normalizeDurationAmount(42)); + assertEquals(WiredConditionVariableAgeMatch.MAX_DURATION_AMOUNT, WiredConditionVariableAgeMatch.normalizeDurationAmount(Integer.MAX_VALUE)); + assertEquals(0L, WiredConditionVariableAgeMatch.durationToMillis(-1, 1)); + assertEquals(1_000L, WiredConditionVariableAgeMatch.durationToMillis(1, 1)); + } + + @Test + void variableAgeModesFallBackToSafeDefaults() { + assertEquals(0, WiredConditionVariableAgeMatch.normalizeTargetTypeExtended(999)); + assertEquals(1, WiredConditionVariableAgeMatch.normalizeTargetTypeExtended(1)); + assertEquals(0, WiredConditionVariableAgeMatch.normalizeCompareValue(99)); + assertEquals(1, WiredConditionVariableAgeMatch.normalizeCompareValue(1)); + assertEquals(0, WiredConditionVariableAgeMatch.normalizeComparison(99)); + assertEquals(2, WiredConditionVariableAgeMatch.normalizeComparison(2)); + assertEquals(1, WiredConditionVariableAgeMatch.normalizeDurationUnit(99)); + assertEquals(7, WiredConditionVariableAgeMatch.normalizeDurationUnit(7)); + } + + @Test + void variableValueModesAndConstantsAreBounded() { + assertEquals(0, WiredConditionVariableValueMatch.normalizeTargetTypeExtended(900)); + assertEquals(3, WiredConditionVariableValueMatch.normalizeTargetTypeExtended(3)); + assertEquals(0, WiredConditionVariableValueMatch.normalizeReferenceMode(5)); + assertEquals(1, WiredConditionVariableValueMatch.normalizeReferenceMode(1)); + assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredConditionVariableValueMatch.normalizeReferenceFurniSource(-1)); + assertEquals(101, WiredConditionVariableValueMatch.normalizeReferenceFurniSource(101)); + assertEquals(2, WiredConditionVariableValueMatch.normalizeComparison(99)); + assertEquals(5, WiredConditionVariableValueMatch.normalizeComparison(5)); + assertEquals(WiredConditionVariableValueMatch.MAX_ABS_REFERENCE_CONSTANT, WiredConditionVariableValueMatch.normalizeReferenceConstantValue(Integer.MAX_VALUE)); + assertEquals(-WiredConditionVariableValueMatch.MAX_ABS_REFERENCE_CONSTANT, WiredConditionVariableValueMatch.normalizeReferenceConstantValue(Integer.MIN_VALUE)); + assertEquals(0, WiredConditionVariableValueMatch.parseInteger("nope")); + assertEquals(123, WiredConditionVariableValueMatch.parseInteger(" 123 ")); + } +}