~singpolyma/biboumi

4cfcc79114d89096219039104674d35ca1aba5ca — Florent Le Coz 8 years ago c3309d0
Check the number of argument of every IRC command received from the server

Each IrcClient callback has a max and min size of argument, we call the
callback only if the parsed message has a correct number of arguments,
otherwise it is ignored (with a warning logged).
2 files changed, 103 insertions(+), 90 deletions(-)

M src/irc/irc_client.cpp
M src/irc/irc_client.hpp
M src/irc/irc_client.cpp => src/irc/irc_client.cpp +19 -7
@@ 150,14 150,26 @@ void IrcClient::parse_in_buffer(const size_t)

      // Call the standard callback (if any), associated with the command
      // name that we just received.
      auto cb = irc_callbacks.find(message.command);
      if (cb != irc_callbacks.end())
      auto it = irc_callbacks.find(message.command);
      if (it != irc_callbacks.end())
        {
          try {
            (this->*(cb->second))(message);
          } catch (const std::exception& e) {
            log_error("Unhandled exception: " << e.what());
          }
          const auto& limits = it->second.second;
          // Check that the Message is well formed before actually calling
          // the callback. limits.first is the min number of arguments,
          // second is the max
          if (message.arguments.size() < limits.first ||
              (limits.second > 0 && message.arguments.size() > limits.second))
            log_warning("Invalid number of arguments for IRC command “" << message.command <<
                        "”: " << message.arguments.size());
          else
            {
              const auto& cb = it->second.first;
              try {
                (this->*(cb))(message);
              } catch (const std::exception& e) {
                log_error("Unhandled exception: " << e.what());
              }
            }
        }
      else
        {

M src/irc/irc_client.hpp => src/irc/irc_client.hpp +84 -83
@@ 336,90 336,91 @@ private:
 */
typedef void (IrcClient::*irc_callback_t)(const IrcMessage&);

static const std::unordered_map<std::string, irc_callback_t> irc_callbacks = {
  {"NOTICE", &IrcClient::on_notice},
  {"002", &IrcClient::forward_server_message},
  {"003", &IrcClient::forward_server_message},
  {"005", &IrcClient::on_isupport_message},
  {"RPL_LISTSTART", &IrcClient::on_rpl_liststart},
  {"321", &IrcClient::on_rpl_liststart},
  {"RPL_LIST", &IrcClient::on_rpl_list},
  {"322", &IrcClient::on_rpl_list},
  {"RPL_LISTEND", &IrcClient::on_rpl_listend},
  {"323", &IrcClient::on_rpl_listend},
  {"RPL_MOTDSTART", &IrcClient::empty_motd},
  {"375", &IrcClient::empty_motd},
  {"RPL_MOTD", &IrcClient::on_motd_line},
  {"372", &IrcClient::on_motd_line},
  {"RPL_MOTDEND", &IrcClient::send_motd},
  {"376", &IrcClient::send_motd},
  {"JOIN", &IrcClient::on_channel_join},
  {"PRIVMSG", &IrcClient::on_channel_message},
  {"353", &IrcClient::set_and_forward_user_list},
  {"332", &IrcClient::on_topic_received},
  {"TOPIC", &IrcClient::on_topic_received},
  {"366", &IrcClient::on_channel_completely_joined},
  {"432", &IrcClient::on_erroneous_nickname},
  {"433", &IrcClient::on_nickname_conflict},
  {"438", &IrcClient::on_nickname_change_too_fast},
  {"001", &IrcClient::on_welcome_message},
  {"PART", &IrcClient::on_part},
  {"ERROR", &IrcClient::on_error},
  {"QUIT", &IrcClient::on_quit},
  {"NICK", &IrcClient::on_nick},
  {"MODE", &IrcClient::on_mode},
  {"PING", &IrcClient::send_pong_command},
  {"PONG", &IrcClient::on_pong},
  {"KICK", &IrcClient::on_kick},
static const std::unordered_map<std::string,
                                std::pair<irc_callback_t, std::pair<std::size_t, std::size_t>>> irc_callbacks = {
  {"NOTICE", {&IrcClient::on_notice, {2, 0}}},
  {"002", {&IrcClient::forward_server_message, {2, 0}}},
  {"003", {&IrcClient::forward_server_message, {2, 0}}},
  {"005", {&IrcClient::on_isupport_message, {0, 0}}},
  {"RPL_LISTSTART", {&IrcClient::on_rpl_liststart, {0, 0}}},
  {"321", {&IrcClient::on_rpl_liststart, {0, 0}}},
  {"RPL_LIST", {&IrcClient::on_rpl_list, {0, 0}}},
  {"322", {&IrcClient::on_rpl_list, {0, 0}}},
  {"RPL_LISTEND", {&IrcClient::on_rpl_listend, {0, 0}}},
  {"323", {&IrcClient::on_rpl_listend, {0, 0}}},
  {"RPL_MOTDSTART", {&IrcClient::empty_motd, {0, 0}}},
  {"375", {&IrcClient::empty_motd, {0, 0}}},
  {"RPL_MOTD", {&IrcClient::on_motd_line, {2, 0}}},
  {"372", {&IrcClient::on_motd_line, {2, 0}}},
  {"RPL_MOTDEND", {&IrcClient::send_motd, {0, 0}}},
  {"376", {&IrcClient::send_motd, {0, 0}}},
  {"JOIN", {&IrcClient::on_channel_join, {1, 0}}},
  {"PRIVMSG", {&IrcClient::on_channel_message, {2, 0}}},
  {"353", {&IrcClient::set_and_forward_user_list, {4, 0}}},
  {"332", {&IrcClient::on_topic_received, {2, 0}}},
  {"TOPIC", {&IrcClient::on_topic_received, {2, 0}}},
  {"366", {&IrcClient::on_channel_completely_joined, {2, 0}}},
  {"432", {&IrcClient::on_erroneous_nickname, {2, 0}}},
  {"433", {&IrcClient::on_nickname_conflict, {2, 0}}},
  {"438", {&IrcClient::on_nickname_change_too_fast, {2, 0}}},
  {"001", {&IrcClient::on_welcome_message, {1, 0}}},
  {"PART", {&IrcClient::on_part, {1, 0}}},
  {"ERROR", {&IrcClient::on_error, {1, 0}}},
  {"QUIT", {&IrcClient::on_quit, {0, 0}}},
  {"NICK", {&IrcClient::on_nick, {1, 0}}},
  {"MODE", {&IrcClient::on_mode, {1, 0}}},
  {"PING", {&IrcClient::send_pong_command, {1, 0}}},
  {"PONG", {&IrcClient::on_pong, {0, 0}}},
  {"KICK", {&IrcClient::on_kick, {3, 0}}},

  {"401", &IrcClient::on_generic_error},
  {"402", &IrcClient::on_generic_error},
  {"403", &IrcClient::on_generic_error},
  {"404", &IrcClient::on_generic_error},
  {"405", &IrcClient::on_generic_error},
  {"406", &IrcClient::on_generic_error},
  {"407", &IrcClient::on_generic_error},
  {"408", &IrcClient::on_generic_error},
  {"409", &IrcClient::on_generic_error},
  {"410", &IrcClient::on_generic_error},
  {"411", &IrcClient::on_generic_error},
  {"412", &IrcClient::on_generic_error},
  {"414", &IrcClient::on_generic_error},
  {"421", &IrcClient::on_generic_error},
  {"422", &IrcClient::on_generic_error},
  {"423", &IrcClient::on_generic_error},
  {"424", &IrcClient::on_generic_error},
  {"431", &IrcClient::on_generic_error},
  {"436", &IrcClient::on_generic_error},
  {"441", &IrcClient::on_generic_error},
  {"442", &IrcClient::on_generic_error},
  {"443", &IrcClient::on_generic_error},
  {"444", &IrcClient::on_generic_error},
  {"446", &IrcClient::on_generic_error},
  {"451", &IrcClient::on_generic_error},
  {"461", &IrcClient::on_generic_error},
  {"462", &IrcClient::on_generic_error},
  {"463", &IrcClient::on_generic_error},
  {"464", &IrcClient::on_generic_error},
  {"465", &IrcClient::on_generic_error},
  {"467", &IrcClient::on_generic_error},
  {"470", &IrcClient::on_generic_error},
  {"471", &IrcClient::on_generic_error},
  {"472", &IrcClient::on_generic_error},
  {"473", &IrcClient::on_generic_error},
  {"474", &IrcClient::on_generic_error},
  {"475", &IrcClient::on_generic_error},
  {"476", &IrcClient::on_generic_error},
  {"477", &IrcClient::on_generic_error},
  {"481", &IrcClient::on_generic_error},
  {"482", &IrcClient::on_generic_error},
  {"483", &IrcClient::on_generic_error},
  {"484", &IrcClient::on_generic_error},
  {"485", &IrcClient::on_generic_error},
  {"487", &IrcClient::on_generic_error},
  {"491", &IrcClient::on_generic_error},
  {"501", &IrcClient::on_generic_error},
  {"502", &IrcClient::on_generic_error},
  {"401", {&IrcClient::on_generic_error, {2, 0}}},
  {"402", {&IrcClient::on_generic_error, {2, 0}}},
  {"403", {&IrcClient::on_generic_error, {2, 0}}},
  {"404", {&IrcClient::on_generic_error, {2, 0}}},
  {"405", {&IrcClient::on_generic_error, {2, 0}}},
  {"406", {&IrcClient::on_generic_error, {2, 0}}},
  {"407", {&IrcClient::on_generic_error, {2, 0}}},
  {"408", {&IrcClient::on_generic_error, {2, 0}}},
  {"409", {&IrcClient::on_generic_error, {2, 0}}},
  {"410", {&IrcClient::on_generic_error, {2, 0}}},
  {"411", {&IrcClient::on_generic_error, {2, 0}}},
  {"412", {&IrcClient::on_generic_error, {2, 0}}},
  {"414", {&IrcClient::on_generic_error, {2, 0}}},
  {"421", {&IrcClient::on_generic_error, {2, 0}}},
  {"422", {&IrcClient::on_generic_error, {2, 0}}},
  {"423", {&IrcClient::on_generic_error, {2, 0}}},
  {"424", {&IrcClient::on_generic_error, {2, 0}}},
  {"431", {&IrcClient::on_generic_error, {2, 0}}},
  {"436", {&IrcClient::on_generic_error, {2, 0}}},
  {"441", {&IrcClient::on_generic_error, {2, 0}}},
  {"442", {&IrcClient::on_generic_error, {2, 0}}},
  {"443", {&IrcClient::on_generic_error, {2, 0}}},
  {"444", {&IrcClient::on_generic_error, {2, 0}}},
  {"446", {&IrcClient::on_generic_error, {2, 0}}},
  {"451", {&IrcClient::on_generic_error, {2, 0}}},
  {"461", {&IrcClient::on_generic_error, {2, 0}}},
  {"462", {&IrcClient::on_generic_error, {2, 0}}},
  {"463", {&IrcClient::on_generic_error, {2, 0}}},
  {"464", {&IrcClient::on_generic_error, {2, 0}}},
  {"465", {&IrcClient::on_generic_error, {2, 0}}},
  {"467", {&IrcClient::on_generic_error, {2, 0}}},
  {"470", {&IrcClient::on_generic_error, {2, 0}}},
  {"471", {&IrcClient::on_generic_error, {2, 0}}},
  {"472", {&IrcClient::on_generic_error, {2, 0}}},
  {"473", {&IrcClient::on_generic_error, {2, 0}}},
  {"474", {&IrcClient::on_generic_error, {2, 0}}},
  {"475", {&IrcClient::on_generic_error, {2, 0}}},
  {"476", {&IrcClient::on_generic_error, {2, 0}}},
  {"477", {&IrcClient::on_generic_error, {2, 0}}},
  {"481", {&IrcClient::on_generic_error, {2, 0}}},
  {"482", {&IrcClient::on_generic_error, {2, 0}}},
  {"483", {&IrcClient::on_generic_error, {2, 0}}},
  {"484", {&IrcClient::on_generic_error, {2, 0}}},
  {"485", {&IrcClient::on_generic_error, {2, 0}}},
  {"487", {&IrcClient::on_generic_error, {2, 0}}},
  {"491", {&IrcClient::on_generic_error, {2, 0}}},
  {"501", {&IrcClient::on_generic_error, {2, 0}}},
  {"502", {&IrcClient::on_generic_error, {2, 0}}},
};

#endif // IRC_CLIENT_INCLUDED