fix(gateway): stop a non-map opcode payload crashing the socket (#2277)

This commit is contained in:
Hampus
2026-08-31 22:14:26 +02:00
committed by GitHub
parent 04e150e4bf
commit 7ce3d71c44
3 changed files with 23 additions and 3 deletions
@@ -56,9 +56,13 @@ handle_authenticated_opcode(presence_update, Data, #{session_pid := Pid} = State
->
handle_presence_update(Data, Pid, State);
handle_authenticated_opcode(voice_state_update, Data, #{session_pid := Pid} = State) when
is_pid(Pid)
is_pid(Pid), is_map(Data)
->
gateway_handler_voice:handle_voice_state_update(Pid, Data, State);
handle_authenticated_opcode(voice_state_update, _Data, State) ->
gateway_handler_encode:close_with_reason(
decode_error, <<"Invalid voice payload">>, State
);
handle_authenticated_opcode(request_guild_members, Data, #{session_pid := Pid} = State) when
is_pid(Pid)
->
@@ -151,7 +151,7 @@ maybe_put(Key, Value, Map) ->
{ok, binary(), map(), term(), [binary()], non_neg_integer(), integer() | undefined,
gateway_sharding:shard() | undefined}
| {error, atom()}.
validate_identify_data(Data) ->
validate_identify_data(Data) when is_map(Data) ->
try
Token = maps:get(<<"token">>, Data),
Properties = maps:get(<<"properties">>, Data),
@@ -163,7 +163,9 @@ validate_identify_data(Data) ->
)
catch
error:{badkey, _} -> {error, missing_required_field}
end.
end;
validate_identify_data(_Data) ->
{error, invalid_data}.
-spec validate_properties(binary(), term(), term(), term(), term(), map()) ->
{ok, binary(), map(), term(), [binary()], non_neg_integer(), integer() | undefined,
@@ -446,6 +446,20 @@ handle_session_start_result_sharding_required_closes_4011_test() ->
),
?assertEqual(constants:close_code_to_num(sharding_required), CloseCode).
identify_with_non_map_payload_closes_test() ->
State = (new_json_state())#{peer_ip => unique_test_peer_ip(<<"198.51.100.61">>)},
{[{close, CloseCode, _Reason}], _NewState} = gateway_handler_dispatch:handle_opcode(
identify, #{<<"d">> => null}, State
),
?assertEqual(constants:close_code_to_num(decode_error), CloseCode).
voice_state_update_with_non_map_payload_closes_test() ->
State = (new_json_state())#{session_pid => self()},
{[{close, CloseCode, _Reason}], _NewState} = gateway_handler_dispatch:handle_opcode(
voice_state_update, #{<<"d">> => <<"not-a-map">>}, State
),
?assertEqual(constants:close_code_to_num(decode_error), CloseCode).
new_json_state() ->
(gateway_handler:new_state())#{
version => 1, encoding => json, compress_ctx => gateway_compress:new_context(none)