mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
fix(multiplayer): reject fractional assignment values
This commit is contained in:
@@ -21,7 +21,7 @@ func apply(payload: Dictionary, expected_player_id: String = "") -> bool:
|
||||
for key in ["match_id", "server_id", "player_id", "slot", "expires_at", "protocol_version", "transport", "endpoint", "join_authorisation"]:
|
||||
if not payload.has(key):
|
||||
return _reject("Assignment response is missing " + key)
|
||||
if not payload["match_id"] is String or not payload["server_id"] is String or not payload["player_id"] is String or not (payload["slot"] is int or payload["slot"] is float) or not payload["expires_at"] is String or not (payload["protocol_version"] is int or payload["protocol_version"] is float) or not payload["transport"] is String or not payload["endpoint"] is String or not payload["join_authorisation"] is String:
|
||||
if not payload["match_id"] is String or not payload["server_id"] is String or not payload["player_id"] is String or not _valid_nonnegative_integer(payload["slot"]) or not payload["expires_at"] is String or not _valid_nonnegative_integer(payload["protocol_version"]) or not payload["transport"] is String or not payload["endpoint"] is String or not payload["join_authorisation"] is String:
|
||||
return _reject("Assignment response contains invalid types")
|
||||
var next_match_id := String(payload["match_id"])
|
||||
var next_server_id := String(payload["server_id"])
|
||||
@@ -71,6 +71,14 @@ static func _valid_endpoint(value: String) -> bool:
|
||||
return port.is_valid_int() and int(port) >= 1 and int(port) <= 65535
|
||||
|
||||
|
||||
static func _valid_nonnegative_integer(value: Variant) -> bool:
|
||||
if value is int:
|
||||
return int(value) >= 0
|
||||
if value is float:
|
||||
return is_finite(float(value)) and float(value) >= 0.0 and float(value) == floor(float(value))
|
||||
return false
|
||||
|
||||
|
||||
func _reject(reason: String) -> bool:
|
||||
available = false
|
||||
error_message = reason
|
||||
|
||||
@@ -21,6 +21,12 @@ func test_assignment_projection_rejects_wrong_shape_or_unsafe_transport() -> voi
|
||||
var short_id := valid.duplicate()
|
||||
short_id["match_id"] = "match-1"
|
||||
assert_true(not assignment.apply(short_id), "short opaque assignment id is rejected")
|
||||
var fractional_slot := valid.duplicate()
|
||||
fractional_slot["slot"] = 1.5
|
||||
assert_true(not assignment.apply(fractional_slot), "fractional slot is rejected")
|
||||
var fractional_protocol := valid.duplicate()
|
||||
fractional_protocol["protocol_version"] = 1.5
|
||||
assert_true(not assignment.apply(fractional_protocol), "fractional protocol version is rejected")
|
||||
assert_true(not assignment.available, "invalid assignment is not exposed")
|
||||
assert_true(not assignment.apply({"match_id": "match-1", "server_id": "server-1", "player_id": "player-1", "slot": 0, "expires_at": "future", "protocol_version": 1, "transport": "udp", "join_authorisation": "signed"}), "unknown transport is rejected")
|
||||
assert_true(not assignment.apply({"match_id": "match-1", "server_id": "server-1", "player_id": "player-1", "slot": 0, "expires_at": "future", "protocol_version": 1, "transport": "steam_sdr", "join_authorisation": ""}), "empty authorisation is rejected")
|
||||
|
||||
@@ -1593,6 +1593,8 @@ Assignment projections and assignment-changed events now enforce the published o
|
||||
|
||||
The WebSocket contract and Go event hub now enforce opaque match and server IDs on assignment notifications, keeping server publication aligned with the Godot client validator.
|
||||
|
||||
Assignment projection now rejects fractional `slot` and `protocol_version` values instead of truncating them, matching the OpenAPI integer contract.
|
||||
|
||||
Signed MatchNet claims now also require exact JSON string/integer types for every identity, protocol, expiry, slot, team, and generation field; string-number coercion is rejected before canonical signature verification.
|
||||
|
||||
Presentation progress: a shared `Game/themes/cosmic_clash_theme.tres` now gives the menu, lobby, matchmaking, and settings surfaces consistent button, input, option, and label styling. The custom-font portion of `TODO.md` remains open until a distributable font asset is selected.
|
||||
|
||||
Reference in New Issue
Block a user