From 80dc1da233a66ab57aa86277d6d6508d78a4036c Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 9 Feb 2024 22:56:20 +0100 Subject: [PATCH] Fix crash when WHOISing invalid MXID --- lib/irc/handler.ex | 90 ++++++++++++++++++++++----------------- test/irc/handler_test.exs | 14 +++++- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/lib/irc/handler.ex b/lib/irc/handler.ex index acb09b3..ca99223 100644 --- a/lib/irc/handler.ex +++ b/lib/irc/handler.ex @@ -1102,51 +1102,61 @@ defmodule M51.IrcConn.Handler do [_server, target | _] -> target end - [local_name, hostname] = String.split(target, ":", parts: 2) + case String.split(target, ":", parts: 2) do + [_] -> + # return ERR_NOSUCHNICK + if target == "" || String.contains?(target, " ") do + send_numeric.("401", ["*", "No such nick"]) + else + send_numeric.("401", [target, "No such nick"]) + end - [member: memberships] = M51.MatrixClient.State.user(matrix_state, target) + [local_name, hostname] -> + [member: memberships] = M51.MatrixClient.State.user(matrix_state, target) - # TODO: pick the most common display name instead - gecos = target + # TODO: pick the most common display name instead + gecos = target - overhead = make_numeric.("353", [target, ""]) |> M51.Irc.Command.format() |> byte_size() + overhead = + make_numeric.("353", [target, ""]) |> M51.Irc.Command.format() |> byte_size() - first_commands = [ - # RPL_WHOISUSER " * :" - make_numeric.("311", [target, local_name, hostname, "*", gecos]) - ] + first_commands = [ + # RPL_WHOISUSER " * :" + make_numeric.("311", [target, local_name, hostname, "*", gecos]) + ] - channel_commands = - memberships - |> Map.keys() - |> Enum.map(fn room_id -> - M51.MatrixClient.State.room_irc_channel(matrix_state, room_id) - end) - |> Enum.sort() - |> M51.Irc.WordWrap.join_tokens(512 - overhead) - |> Enum.map(fn line -> - line = line |> String.trim_trailing() - - if line != "" do - # RPL_WHOISCHANNELS " :[prefix]{ [prefix]}" - make_numeric.("319", [target, line]) - end - end) - |> Enum.filter(fn line -> line != nil end) - - last_commands = [ - # RPL_WHOISSERVER " :" - make_numeric.("312", [target, hostname, hostname]), - # RPL_WHOISACCOUNT " :is logged in as" - make_numeric.("330", [target, target, "is logged in as"]), - # RPL_ENDOFWHOIS - make_numeric.("318", [target, "End of WHOIS"]) - ] - - send_batch.( - Enum.concat([first_commands, channel_commands, last_commands]), - "labeled-response" - ) + channel_commands = + memberships + |> Map.keys() + |> Enum.map(fn room_id -> + M51.MatrixClient.State.room_irc_channel(matrix_state, room_id) + end) + |> Enum.sort() + |> M51.Irc.WordWrap.join_tokens(512 - overhead) + |> Enum.map(fn line -> + line = line |> String.trim_trailing() + + if line != "" do + # RPL_WHOISCHANNELS " :[prefix]{ [prefix]}" + make_numeric.("319", [target, line]) + end + end) + |> Enum.filter(fn line -> line != nil end) + + last_commands = [ + # RPL_WHOISSERVER " :" + make_numeric.("312", [target, hostname, hostname]), + # RPL_WHOISACCOUNT " :is logged in as" + make_numeric.("330", [target, target, "is logged in as"]), + # RPL_ENDOFWHOIS + make_numeric.("318", [target, "End of WHOIS"]) + ] + + send_batch.( + Enum.concat([first_commands, channel_commands, last_commands]), + "labeled-response" + ) + end {"BATCH", [first_param | params]} -> {first_char, reference_tag} = String.split_at(first_param, 1) diff --git a/test/irc/handler_test.exs b/test/irc/handler_test.exs index fa63dd1..113ff46 100644 --- a/test/irc/handler_test.exs +++ b/test/irc/handler_test.exs @@ -828,7 +828,7 @@ defmodule M51.IrcConn.HandlerTest do assert_line("BATCH :-#{batch_id}\r\n") end - test "WHOIS", %{handler: handler} do + test "WHOIS unknown user", %{handler: handler} do do_connection_registration(handler) send(handler, cmd("@label=l1 WHOIS unknown_user:example.com")) @@ -855,6 +855,18 @@ defmodule M51.IrcConn.HandlerTest do assert_line("BATCH :-#{batch_id}\r\n") end + test "WHOIS non-MXID", %{handler: handler} do + do_connection_registration(handler) + + send(handler, cmd("@label=l1 WHOIS not_enough_colons")) + + assert_line("@label=l1 :server. 401 foo:example.org not_enough_colons :No such nick\r\n") + + send(handler, cmd("@label=l1 WHOIS :with spaces")) + + assert_line("@label=l1 :server. 401 foo:example.org * :No such nick\r\n") + end + test "MODE on user", %{handler: handler} do do_connection_registration(handler)