Commit 4b282dd6 authored by Luke Bratch's avatar Luke Bratch

Fix various issues where strncmp was only comparing a substring.

This fixes issues such as when JOINing a channel whose name is a substring of another channel, things like PARTing don't work properly.
parent a16d9bde
......@@ -14,6 +14,8 @@ Can memory usage be reduced further? (e.g. better channel struct management)
Ability to load new certificate whilst running.
JOINing a channel that is a substring of another channel breaks all sorts (e.g. both #blabouncer and #blabounce).
Are any other strncmps incorrect (i.e. just checking a substring)?
Topic is stored incorrectly when the setter's host was an IPv6 address (colon search issue?).
Crash when requesting 30 hour replay.
......@@ -675,7 +675,7 @@ int createchannel(struct channel *channels, struct ircdstate *ircdstate, char *n
if (arrslot < 0) {
arrslot = ircdstate->maxchannelcount;
ircdstate->maxchannelcount++;
debugprint(DEBUG_FULL, "createchannel(): using new slot slot %d.\n", arrslot);
debugprint(DEBUG_FULL, "createchannel(): using new slot %d.\n", arrslot);
}
// If we got a valid slot...
......@@ -713,16 +713,18 @@ int setchanneltopicwhotime(struct channel *channels, int maxchannelcount, char *
debugprint(DEBUG_FULL, "setchanneltopicwhotime(): when: '%s' with length '%ld'.\n", when, strlen(when));
for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, channelname, strlen(channelname)) == 0) {
if ((strlen(channels[i].name) == strlen(channelname)) && (strncmp(channels[i].name, channelname, strlen(channelname)) == 0)) {
strncpy(channels[i].topicwho, who, strlen(who));
channels[i].topicwho[strlen(who)] = '\0';
strncpy(channels[i].topicwhen, when, strlen(when));
channels[i].topicwhen[strlen(when)] = '\0';
debugprint(DEBUG_FULL, "setchanneltopicwhotime(): set channel '%s' to '%s', '%s'.\n", channels[i].name, channels[i].topicwho, channels[i].topicwhen);
return 1;
}
}
// TODO - Make a failed return do something to callers
debugprint(DEBUG_FULL, "setchanneltopicwhotime(): failed to set channel topic who/when.\n");
return 0;
}
......@@ -730,9 +732,10 @@ int setchanneltopic(struct channel *channels, int maxchannelcount, char *channel
debugprint(DEBUG_FULL, "setchanneltopic(): given '%s' and '%s'.\n", channelname, topic);
for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, channelname, strlen(channelname)) == 0) {
if ((strlen(channels[i].name) == strlen(channelname)) && (strncmp(channels[i].name, channelname, strlen(channelname)) == 0)) {
strncpy(channels[i].topic, topic, strlen(topic));
channels[i].topic[strlen(topic)] = '\0';
debugprint(DEBUG_FULL, "setchanneltopic(): set channel '%s' to '%s'.\n", channels[i].name, channels[i].topic);
return 1;
}
}
......@@ -763,7 +766,7 @@ int removechannel(struct channel *channels, int maxchannelcount, char *name) {
// Find the channel in the channel array...
for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
if ((strlen(channels[i].name) == strlen(name)) && (strncmp(channels[i].name, name, strlen(name)) == 0)) {
// ..and NULL its name (0th character = '\0')
channels[i].name[0] = '\0';
// Set nicks to blank
......@@ -782,11 +785,11 @@ int removechannel(struct channel *channels, int maxchannelcount, char *name) {
}
// Check if we have the NAMES for the channel 'name' already.
// Return the 1 if we do, 0 if we don't, or -1 if there's an error.
// Return 1 if we do, 0 if we don't, or -1 if there's an error.
int channelgotnames(struct channel *channels, int maxchannelcount, char *name) {
debugprint(DEBUG_FULL, "channelgotnames(): given '%s'.\n", name);
for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
if ((strlen(channels[i].name) == strlen(name)) && strncmp(channels[i].name, name, strlen(name)) == 0) {
if (channels[i].gotnames) {
debugprint(DEBUG_FULL, "channelgotnames(): channel '%s' gotnames was set, returning '%d'.\n", channels[i].name, channels[i].gotnames);
return 1;
......@@ -814,7 +817,7 @@ int inchannel(struct channel *channels, int maxchannelcount, char *name) {
}
for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
if ((strlen(channels[i].name) == strlen(name)) && (strncmp(channels[i].name, name, strlen(name)) == 0)) {
debugprint(DEBUG_FULL, "inchannel(): in channel '%s'.\n", name);
return 1;
}
......@@ -831,7 +834,7 @@ int inchannel(struct channel *channels, int maxchannelcount, char *name) {
int channelindex(struct channel *channels, int maxchannelcount, char *name) {
debugprint(DEBUG_FULL, "channelindex(): given '%s'.\n", name);
for (int i = 0; i < maxchannelcount; i++) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
if ((strlen(channels[i].name) == strlen(name)) && (strncmp(channels[i].name, name, strlen(name)) == 0)) {
return i;
}
}
......@@ -913,7 +916,8 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set
extractnickfromprefix(tokens[0], 1);
// Check if we're currently in this channel or if the log line is from us
if (!inchannel(channels, ircdstate->maxchannelcount, tokens[2] + offset) || strncmp(tokens[0], ircdstate->ircnick, strlen(tokens[0])) == 0) {
if (!inchannel(channels, ircdstate->maxchannelcount, tokens[2] + offset) ||
((strlen(tokens[0]) == strlen(ircdstate->ircnick)) && (strncmp(tokens[0], ircdstate->ircnick, strlen(tokens[0])) == 0))) {
debugprint(DEBUG_FULL, "Not sending '%s' replay line '%s'.\n", tokens[1], outgoingmsg);
free(strcopyPtr);
continue;
......@@ -924,7 +928,7 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set
if (strncmp(tokens[1], "NICK", strlen("NICK")) == 0) {
extractnickfromprefix(tokens[0], 1);
if (strncmp(tokens[0], ircdstate->ircnick, strlen(tokens[0])) == 0) {
if ((strlen(tokens[0]) == strlen(ircdstate->ircnick)) && (strncmp(tokens[0], ircdstate->ircnick, strlen(tokens[0])) == 0)) {
debugprint(DEBUG_FULL, "Not sending '%s' replay line '%s'.\n", tokens[1], outgoingmsg);
free(strcopyPtr);
continue;
......
......@@ -134,7 +134,7 @@ int logline(char *str, struct ircdstate *ircdstate, char *basedir, int type) {
// Build the log filename
// If the message was sent to us, then log it in the sender's log file
if (strncmp(tokens[2], ircdstate->ircnick, strlen(tokens[0])) == 0) {
if ((strlen(tokens[2]) == strlen(tokens[0])) && (strncmp(tokens[2], ircdstate->ircnick, strlen(tokens[0])) == 0)) {
if (!snprintf(filename, MAXCHAR, "%s/logs/%s.log", basedir, from)) {
debugprint(DEBUG_CRIT, "Error while preparing log filename for from name, returning!\n");
return 0;
......
......@@ -190,7 +190,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int
char *prefixcopy = strdup(tokens[0]);
// Just get the nick for comparison
extractnickfromprefix(prefixcopy, 1);
if (strncmp(prefixcopy, ircdstate->ircnick, strlen(tokens[0])) == 0) {
if ((strlen(prefixcopy) == strlen(ircdstate->ircnick)) && (strncmp(prefixcopy, ircdstate->ircnick, strlen(tokens[0])) == 0)) {
debugprint(DEBUG_FULL, "Server JOIN: nick is ours ('%s' vs '%s').\n", prefixcopy, ircdstate->ircnick);
// TODO - Saner way to initialise this since we don't have the variables yet?
// TODO - Defaulting to type '=' which is "public" since I don't know what else to guess.
......@@ -231,7 +231,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int
char *prefixcopy = strdup(tokens[0]);
// Just get the nick for comparison
extractnickfromprefix(prefixcopy, 1);
if (strncmp(prefixcopy, ircdstate->ircnick, strlen(tokens[0])) == 0) {
if ((strlen(prefixcopy) == strlen(ircdstate->ircnick)) && (strncmp(prefixcopy, ircdstate->ircnick, strlen(tokens[0])) == 0)) {
debugprint(DEBUG_FULL, "Server PART: nick is ours ('%s' vs '%s').\n", prefixcopy, ircdstate->ircnick);
removechannel(channels, ircdstate->maxchannelcount, tokens[2]);
} else {
......@@ -454,7 +454,7 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int
char *svrprefixcopy = strdup(tokens[0]);
// Just get the nick for comparison
extractnickfromprefix(svrprefixcopy, 1);
if (strncmp(ircdstate->ircnick, svrprefixcopy, strlen(ircdstate->ircnick)) == 0) {
if ((strlen(ircdstate->ircnick) && strlen(svrprefixcopy)) && (strncmp(ircdstate->ircnick, svrprefixcopy, strlen(ircdstate->ircnick)) == 0)) {
debugprint(DEBUG_FULL, "Server NICK: nick is ours ('%s' vs '%s').\n", svrprefixcopy, ircdstate->ircnick);
// Make a copy of the old nickuserhost for updategreetings() below
char *nickuserhostcpy = strdup(ircdstate->nickuserhost);
......@@ -773,7 +773,8 @@ int processservermessage(SSL *server_ssl, char *str, struct client *clients, int
debugprint(DEBUG_FULL, "Server CAP found and it is: %s with length %zd! Analysing...\n", tokens[1], strlen(tokens[1]));
// If the server said "CAP <ournick> ACK :multi-prefix" then it must have approved our CAP multi-prefix request
if (counter == 5) {
if (strncmp(tokens[2], ircdstate->ircnick, strlen(tokens[2])) == 0 &&
if (strlen(tokens[2]) == strlen(ircdstate->ircnick) &&
strncmp(tokens[2], ircdstate->ircnick, strlen(tokens[2])) == 0 &&
strncmp(tokens[3], "ACK", strlen(tokens[3])) == 0 &&
strncmp(tokens[4], ":multi-prefix", strlen(tokens[4])) == 0) {
ircdstate->capmultiprefix = 1;
......@@ -1005,6 +1006,7 @@ int processclientmessage(SSL *server_ssl, char *str, struct client *clients, int
// Send topic (or lack thereof) to client
// If there isn't one set (we guess this if topic timestamp is 0), send 331 RPL_NOTOPIC
// TODO - What if the topic is "0"?
if (strncmp(channels[i].topicwhen, "0", 1) == 0) {
// Prepare the no topic message...
if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 331 %s %s :No topic is set.", ircdstate->ircdname, ircdstate->ircnick, channels[i].name)) {
......@@ -1172,6 +1174,7 @@ int processclientmessage(SSL *server_ssl, char *str, struct client *clients, int
if (strncasecmp(tokens[0], "MODE", strlen(tokens[0])) == 0) {
debugprint(DEBUG_FULL, "Client MODE found and it is: %s with length %zd! Analysing...\n", tokens[0], strlen(tokens[0]));
// Is it a ban MODE request (MODE #channel b)?
// TODO - Can something else beginning with "b" be in this position? Need a length comparison?
if (counter >= 3 && strncmp(tokens[2], "b", strlen("b")) == 0) {
debugprint(DEBUG_FULL, "Ban MODE request received, marking as pending.\n");
clients[clientindex].pendingban = 1;
......
......@@ -356,7 +356,7 @@ int lastspokesecondsago(char *nick, char *basedir) {
// Was it said by our 'nick'? Disable extractnickfromprefix() debugging
// as it gets very noisy when we call it from here.
extractnickfromprefix(tokens[1], 0);
if (strncmp(tokens[1], nick, strlen(nick))) {
if ((strlen(tokens[1]) == strlen(nick)) && (strncmp(tokens[1], nick, strlen(nick)))) {
// Not our 'nick', continue
continue;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment