jcs
/wallops
/amendments
/84
irc: Cope with input buffer getting full of non-lines
This should only happen on a rogue server, but we shouldn't fall
over ourselves dealing with it.
jcs made amendment 84 2 months ago
--- irc.c Wed Sep 11 09:58:59 2024
+++ irc.c Wed Sep 11 16:25:38 2024
@@ -359,10 +359,23 @@ irc_get_line(struct irc_connection *conn, size_t *rets
if (conn->ibuf[n + 1] != '\n')
continue;
- memcpy(conn->line, conn->ibuf, n + 1);
- conn->line[n] = '\0';
- if (retsize != NULL)
- *retsize = n + 1;
+ if (conn->flushing_ibuf) {
+ conn->flushing_ibuf = false;
+ conn->line[0] = '\0';
+ } else if (n + 1 >= sizeof(conn->line) - 1) {
+ /*
+ * Line is too long to process but we can't take part of it,
+ * so bail on it and hope it wasn't something important :(
+ */
+ chatter_printf(conn->chatter, NULL, NULL,
+ "*!* Line too long to process");
+ conn->line[0] = '\0';
+ } else {
+ memcpy(conn->line, conn->ibuf, n + 1);
+ conn->line[n] = '\0';
+ if (retsize != NULL)
+ *retsize = n + 1;
+ }
if (n == conn->ibuflen - 2) {
conn->ibuflen = 0;
@@ -375,6 +388,18 @@ irc_get_line(struct irc_connection *conn, size_t *rets
return conn->line;
}
+ if (n >= sizeof(conn->ibuf) - 1) {
+ /*
+ * ibuf is full with no newline but we can't empty the buffer and
+ * start the next iteration in the middle of this line, so
+ * consider ibuf bogus until we see a newline.
+ */
+ conn->flushing_ibuf = true;
+ conn->ibuflen = 0;
+ chatter_printf(conn->chatter, NULL, NULL,
+ "*!* ibuf with no newline, flushing");
+ }
+
return NULL;
}
@@ -411,7 +436,10 @@ irc_process_server(struct irc_connection *conn)
memset(&msg, 0, sizeof(msg));
word = strsep(&line, " ");
-
+ if (word == NULL)
+ /* server sent us a blank line? */
+ return false;
+
/* extract source before command */
if (word[0] == ':') {
/* ":server.name 001 jcs :Hi" -> msg.source=server.name */
@@ -667,6 +695,7 @@ irc_process_server(struct irc_connection *conn)
if ((channel = irc_find_channel(conn, msg.arg[0]))) {
if (strcmp(user->nick, conn->nick) == 0) {
irc_dealloc_channel(channel);
+ channel = NULL;
/* we don't need to print anything */
} else {
irc_remove_nick_from_channel(channel, user->nick);
@@ -1179,10 +1208,8 @@ irc_create_channel(struct irc_connection *conn, char *
short n;
SLIST_FOREACH(channel, &conn->channels_list, list) {
- if (strcasecmp(channel->name, channame) == 0) {
- /* TODO: chatter_switch_to_channel(channel) */
+ if (strcasecmp(channel->name, channame) == 0)
return channel;
- }
}
channel = xmalloczero(sizeof(struct irc_channel));
--- irc.h Tue Sep 10 09:17:34 2024
+++ irc.h Wed Sep 11 15:54:07 2024
@@ -92,6 +92,7 @@ struct irc_connection {
char line[512];
short ibuflen;
short linelen;
+ bool flushing_ibuf;
/* docs say 4*MTU+1024, but MTU will probably be <1500 */
unsigned char tcp_buf[(4 * 1500) + 2048];
};