diff --git a/src/irc/core/irc-cap.c b/src/irc/core/irc-cap.c index 2c2df7f9..1c5e1d18 100644 --- a/src/irc/core/irc-cap.c +++ b/src/irc/core/irc-cap.c @@ -78,7 +78,16 @@ static void cap_emit_signal (IRC_SERVER_REC *server, char *cmd, char *args) { char *signal_name; - signal_name = g_strdup_printf("server cap %s %s", cmd, args? args: ""); + if (args == NULL) + return; + + /* Cap the number of unique CAP signals emitted per server to prevent + * unbounded signal-name interning from server-controlled CAP tokens. */ + if (server->cap_supported == NULL || + g_hash_table_size(server->cap_supported) > 256) + return; + + signal_name = g_strdup_printf("server cap %s %s", cmd, args); signal_emit(signal_name, 1, server); g_free(signal_name); } diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index 68da0e27..3087649e 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -730,6 +730,16 @@ static void dcc_chat_msg(CHAT_DCC_REC *dcc, const char *msg) if (*msg != 1) return; + /* Cap the CTCP body length that is concatenated into the signal name. The + * body comes from a remote peer on an established DCC CHAT connection + * and is passed as the second argument to any matching signal handler + * (including loaded perl scripts). A modest cap limits the attack surface + * for the dynamic-signal-name dispatch and aligns with the convention + * used for CTCP-over-IRC. */ + if (strlen(msg+1) > 256) { + return; + } + /* get ctcp command, remove \001 chars */ event = g_strconcat(reply ? "dcc reply " : "dcc ctcp ", msg+1, NULL); if (event[strlen(event)-1] == 1) event[strlen(event)-1] = '\0';