Skip to content

Commit

Permalink
Fix crash when WHOISing invalid MXID
Browse files Browse the repository at this point in the history
  • Loading branch information
progval committed Feb 9, 2024
1 parent 8cf8f99 commit 82f6722
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 41 deletions.
87 changes: 47 additions & 40 deletions lib/irc/handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1102,51 +1102,58 @@ defmodule M51.IrcConn.Handler do
[_server, target | _] -> target
end

[local_name, hostname] = String.split(target, ":", parts: 2)
case String.split(target, ":", parts: 2) do
[_] ->
if target == "" || String.contains?(target, " ") do
send_numeric.("401", ["*", "No such nick"]) # ERR_NOSUCHNICK
else
send_numeric.("401", [target, "No such nick"]) # ERR_NOSUCHNICK
end
[local_name, hostname] ->
[member: memberships] = M51.MatrixClient.State.user(matrix_state, target)

[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 "<nick> <username> <host> * :<realname>"
make_numeric.("311", [target, local_name, hostname, "*", gecos])
]

first_commands = [
# RPL_WHOISUSER "<nick> <username> <host> * :<realname>"
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 "<nick> :[prefix]<channel>{ [prefix]<channel>}"
make_numeric.("319", [target, line])
end
end)
|> Enum.filter(fn line -> line != nil end)

last_commands = [
# RPL_WHOISSERVER "<nick> <server> :<server info>"
make_numeric.("312", [target, hostname, hostname]),
# RPL_WHOISACCOUNT "<nick> <account> :is logged in as"
make_numeric.("330", [target, target, "is logged in as"]),
# RPL_ENDOFWHOIS
make_numeric.("318", [target, "End of WHOIS"])
]

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 "<nick> :[prefix]<channel>{ [prefix]<channel>}"
make_numeric.("319", [target, line])
end
end)
|> Enum.filter(fn line -> line != nil end)

last_commands = [
# RPL_WHOISSERVER "<nick> <server> :<server info>"
make_numeric.("312", [target, hostname, hostname]),
# RPL_WHOISACCOUNT "<nick> <account> :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"
)
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)
Expand Down
14 changes: 13 additions & 1 deletion test/irc/handler_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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 used", %{handler: handler} do
do_connection_registration(handler)

send(handler, cmd("@label=l1 WHOIS unknown_user:example.com"))
Expand All @@ -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)

Expand Down

0 comments on commit 82f6722

Please sign in to comment.