commit d17527b115335a229754594c557db7cebea10eda
parent 0e07631cb4b92b74d6fe7c027d41cd7cc80e576d
Author: Andrew Kloet <andrew@kloet.net>
Date: Sun, 29 Mar 2026 13:49:55 -0400
fix off-by-one and use safer str functions
Diffstat:
| M | nio.c | | | 103 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
1 file changed, 52 insertions(+), 51 deletions(-)
diff --git a/nio.c b/nio.c
@@ -274,7 +274,7 @@ dial(const char *host, const char *service)
if (ssl) {
SSL_load_error_strings();
SSL_library_init();
- srv.ctx = SSL_CTX_new(SSLv23_client_method());
+ srv.ctx = SSL_CTX_new(TLS_client_method());
if (!srv.ctx)
return "Could not initialize ssl context.";
srv.ssl = SSL_new(srv.ctx);
@@ -326,7 +326,7 @@ chadd(const char *name, int joined)
return -1;
if ((n = chfind(name)) > 0)
return n;
- strcpy(chl[nch].name, name);
+ strlcpy(chl[nch].name, name, sizeof(chl[nch].name));
chl[nch].sz = LogSz;
chl[nch].buf = malloc(LogSz);
if (!chl[nch].buf)
@@ -345,13 +345,13 @@ static int
chdel(char *name)
{
int n = chfind(name);
-
if (n <= 0) return 0;
free(chl[n].buf);
+
+ if (n < nch - 1)
+ memmove(&chl[n], &chl[n + 1], (nch - n - 1) * sizeof(struct Chan));
nch--;
- if (n < nch) /* Shift the channel buffers down. */
- memmove(&chl[n], &chl[n + 1], (nch - n) * sizeof(struct Chan));
- if (ch >= n) /* Decrement the selected channel. */
+ if (ch > n || ch >= nch)
ch = (ch > 0) ? ch - 1 : 0;
tdrawbar();
return 1;
@@ -431,11 +431,8 @@ pushf(int cn, const char *fmt, ...)
gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec, s);
fflush(logfp);
}
- strcat(c->eol, "\n");
- if (n >= LineLen - 1)
- c->eol += LineLen - 1;
- else
- c->eol += n + 1;
+ strlcat(c->buf, "\n", c->sz);
+ c->eol = c->buf + strlen(c->buf);
if (cn == ch && c->n == 0) {
char *p = c->eol - n - 1;
@@ -452,7 +449,7 @@ scmd(char *usr, char *cmd, char *par, char *data)
IrcCmd type = CMD_UNKNOWN;
int c;
char *pm = strtok(par, " ");
- char *chan;
+ char *chan;
for (size_t i = 0; i < sizeof(cmd_map)/sizeof(cmd_map[0]); i++) {
if (!strcmp(cmd, cmd_map[i].name)) {
@@ -492,32 +489,32 @@ scmd(char *usr, char *cmd, char *par, char *data)
if (pm) pushf(chfind(pm), "-!- %s has %s %s",
usr, (type == JOIN ? "joined" : "left"), pm);
break;
- case QUIT:
- break;
+ case QUIT:
+ break;
case ERR_FORWARD: {
- char *oldch = strtok(NULL, " ");
- char *newch = strtok(NULL, " ");
- if (!oldch || !newch || !(c = chfind(oldch)))
- break;
- chl[c].name[0] = 0;
- strncat(chl[c].name, newch, ChanLen - 1);
- tdrawbar();
- break;
+ char *oldch = strtok(NULL, " ");
+ char *newch = strtok(NULL, " ");
+ if (!oldch || !newch || !(c = chfind(oldch)))
+ break;
+ chl[c].name[0] = 0;
+ strlcat(chl[c].name, newch, sizeof(chl[c].name));
+ tdrawbar();
+ break;
}
case ERR_FULL:
case ERR_INVITE:
case ERR_BANNED:
case ERR_BADKEY:
- if (!(pm = strtok(NULL, " ")))
+ if (!(pm = strtok(NULL, " ")))
break;
- chdel(pm);
- pushf(0, "-!- Cannot join %s (%s)", pm, cmd);
- tredraw();
- break;
- case ERR_NICKNAMEINUSE:
- strncat(nick, "_", sizeof(nick) - strlen(nick) - 1);
- sndf("NICK %s", nick);
- break;
+ chdel(pm);
+ pushf(0, "-!- Cannot join %s (%s)", pm, cmd);
+ tredraw();
+ break;
+ case ERR_NICKNAMEINUSE:
+ strlcat(nick, "_", sizeof(nick));
+ sndf("NICK %s", nick);
+ break;
case CAP:
if (!(pm = strtok(NULL, " "))) break;
if (!strcmp(pm, "LS"))
@@ -528,15 +525,15 @@ scmd(char *usr, char *cmd, char *par, char *data)
sndf("CAP END");
break;
case AUTHENTICATE:
- if (!par || *par != '+') break;
- if (!is_empty(cert)) {
+ if (!par || *par != '+') break;
+ if (!is_empty(cert)) {
sndf("AUTHENTICATE +");
- } else {
+ } else {
char raw[512];
int r = snprintf(raw, sizeof(raw), "%s%c%s%c%s", nick, 0, nick, 0, key);
sndf("AUTHENTICATE %s", b64_enc((unsigned char *)raw, r));
- }
- break;
+ }
+ break;
case SASL_OK:
case SASL_ERR:
sndf("CAP END");
@@ -580,14 +577,18 @@ uparse(char *m)
case 'l': /* Leave channels. */
p += 1 + (p[1] == ' ');
if (!*p) {
- if (ch == 0) return; /* Cannot leave server window. */
- p = chl[ch].name;
+ if (ch == 0) return;
+ static char buf[ChanLen];
+ strlcpy(buf, chl[ch].name, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ p = buf;
}
- p = strtok(p, " ");
- while (p) {
- if (chdel(p) && strchr("&#!+", p[0]))
- sndf("PART %s", p); /* PART should not be sent for users. */
- p = strtok(0, " ");
+ char *token = strtok(p, " ");
+ while (token) {
+ char *next = strtok(NULL, " ");
+ if (chdel(token) && strchr("&#!+", token[0]))
+ sndf("PART %s", token);
+ token = next;
}
tredraw();
return;
@@ -636,7 +637,7 @@ tinit(void)
if (has_colors() == TRUE) {
start_color();
use_default_colors();
- init_pair(1, COLOR_WHITE, COLOR_BLUE);
+ init_pair(1, COLOR_WHITE, COLOR_BLACK);
wbkgd(scr.sw, COLOR_PAIR(1));
}
}
@@ -874,9 +875,8 @@ main(int argc, char *argv[])
panic("fopen: logfile");
break;
case 'n':
- if (strlen(optarg) >= sizeof nick)
+ if (strlcpy(nick, optarg, sizeof(nick)) >= sizeof(nick))
goto usage;
- strcpy(nick, optarg);
break;
case 'T':
ssl = 0;
@@ -891,15 +891,16 @@ main(int argc, char *argv[])
port = optarg;
break;
case 'c':
- snprintf(cert, sizeof(cert), "%s", optarg);
+ if (strlcpy(cert, optarg, sizeof(cert)) >= sizeof(cert))
+ goto usage;
break;
}
if (!user)
user = "anonymous";
- if (!nick[0] && ircnick && strlen(ircnick) < sizeof nick)
- strcpy(nick, ircnick);
- if (!nick[0] && strlen(user) < sizeof nick)
- strcpy(nick, user);
+ if (!nick[0] && ircnick)
+ strlcpy(nick, ircnick, sizeof(nick));
+ if (!nick[0])
+ strlcpy(nick, user, sizeof(nick));
if (!nick[0])
goto usage;
tinit();