diff options
Diffstat (limited to 'FICS/comproc.c')
-rw-r--r-- | FICS/comproc.c | 127 |
1 files changed, 90 insertions, 37 deletions
diff --git a/FICS/comproc.c b/FICS/comproc.c index f1a95d4..a7a5ea1 100644 --- a/FICS/comproc.c +++ b/FICS/comproc.c @@ -36,6 +36,17 @@ Markus Uhlin 24/11/19 Improved com_news(). plogins: fscanf: added width specification + Markus Uhlin 25/03/08 Calc string length once + Markus Uhlin 25/03/11 Fixed possibly uninitialized + value 'rat' in who_terse(). + Markus Uhlin 25/03/16 Fixed use of 32-bit 'time_t'. + Markus Uhlin 25/03/16 Fixed untrusted array index. + Markus Uhlin 25/03/25 com_unalias: fixed overflowed + array index read/write. + Markus Uhlin 25/07/21 com_who: fixed multiplication + result converted to larger type. + Markus Uhlin 25/07/24 Fixed use of potentially + dangerous functions. */ #include "stdinclude.h" @@ -44,6 +55,7 @@ #include <sys/resource.h> #include <err.h> +#include <errno.h> #include "board.h" #include "command.h" @@ -380,11 +392,18 @@ com_stats_rating(char *hdr, statistics *stats, char *dest, const size_t dsize) stats->num); if (stats->whenbest) { + struct tm res = {0}; + snprintf(tmp, sizeof tmp, " %d", stats->best); strlcat(dest, tmp, dsize); - strftime(tmp, sizeof tmp, " (%d-%b-%y)", - localtime((time_t *) &stats->whenbest)); - strlcat(dest, tmp, dsize); + + errno = 0; + + if (localtime_r(&stats->whenbest, &res) != NULL) { + if (strftime(tmp, sizeof tmp, " (%d-%b-%y)", &res) != 0) + strlcat(dest, tmp, dsize); + } else + warn("%s: localtime_r", __func__); } if (strlcat(dest, "\n", dsize) >= dsize) { @@ -400,11 +419,10 @@ com_stats(int p, param_list param) (MAX_OBSERVE > MAX_SIMUL ? MAX_OBSERVE : MAX_SIMUL) char line[255] = { '\0' }; char tmp[255] = { '\0' }; - int g, i; + int g, i, t; int numbers[NUMBERS_SIZE]; int onTime; int p1, connected; - time_t t; if (param[0].type == TYPE_WORD) { if (!FindPlayer(p, param[0].val.word, &p1, &connected)) @@ -423,9 +441,11 @@ com_stats(int p, param_list param) snprintf(tmp, sizeof tmp, " Idle: %s\n", hms_desc(player_idle(p1))); } else { - if ((t = player_lastdisconnect(p1))) { + time_t last; + + if ((last = player_lastdisconnect(p1)) != 0) { snprintf(tmp, sizeof tmp, "(Last disconnected %s):\n", - strltime(&t)); + strltime(&last)); } else strlcpy(tmp, "(Never connected.)\n", sizeof tmp); } @@ -573,9 +593,14 @@ com_stats(int p, param_list param) if (connected && parray[p1].registered && (p == p1 || parray[p].adminLevel > 0)) { - char *timeToStr = ctime((time_t *) &parray[p1].timeOfReg); + char timeToStr[30] = { '\0' }; + + errno = 0; + + if (ctime_r(&parray[p1].timeOfReg, timeToStr) == NULL) + warn("%s: ctime_r", __func__); + timeToStr[strcspn(timeToStr, "\n")] = '\0'; - timeToStr[strlen(timeToStr) - 1] = '\0'; pprintf(p, "\n"); onTime = ((time(NULL) - parray[p1].logon_time) + @@ -737,9 +762,10 @@ plogins(int p, char *fname) FILE *fp = NULL; char ipstr[20] = { '\0' }; char loginName[MAX_LOGIN_NAME + 1] = { '\0' }; - int inout, registered; + int registered = 0; long int lval = 0; time_t tval = 0; + uint16_t inout = 0; if ((fp = fopen(fname, "r")) == NULL) { pprintf(p, "Sorry, no login information available.\n"); @@ -750,7 +776,7 @@ plogins(int p, char *fname) _Static_assert(19 < ARRAY_SIZE(loginName), "'loginName' too small"); while (!feof(fp)) { - if (fscanf(fp, "%d %19s %ld %d %19s\n", &inout, loginName, + if (fscanf(fp, "%hu %19s %ld %d %19s\n", &inout, loginName, &lval, ®istered, ipstr) != 5) { fprintf(stderr, "FICS: Error in login info format. " "%s\n", fname); @@ -760,8 +786,13 @@ plogins(int p, char *fname) tval = lval; - pprintf(p, "%s: %-17s %-6s", strltime(&tval), loginName, - inout_string[inout]); + if (inout >= ARRAY_SIZE(inout_string)) { + warnx("%s: %s: 'inout' too large (%u)", __func__, fname, + inout); + } else { + pprintf(p, "%s: %-17s %-6s", strltime(&tval), loginName, + inout_string[inout]); + } if (parray[p].adminLevel > 0) pprintf(p, " from %s\n", ipstr); @@ -842,6 +873,8 @@ who_terse(int p, int num, int *plist, int type) rat = parray[p1].s_stats.rating; else if (type == light_rat) rat = parray[p1].l_stats.rating; + else // Fallback to std... + rat = parray[p1].s_stats.rating; if (type == none) { strlcpy(ptmp, " ", sizeof ptmp); @@ -866,8 +899,10 @@ who_terse(int p, int num, int *plist, int type) } if (p == p1) { - psprintf_highlight(p, ptmp + strlen(ptmp), - sizeof ptmp - strlen(ptmp), "%s", parray[p1].name); + const size_t len = strlen(ptmp); + + psprintf_highlight(p, ptmp + len, + sizeof ptmp - len, "%s", parray[p1].name); } else { strlcat(ptmp, parray[p1].name, sizeof ptmp); } @@ -929,9 +964,12 @@ who_verbose(int p, int num, int plist[]) p1WithAttrs[17] = '\0'; if (p == p1) { + size_t len; + strlcpy(tmp, " ", sizeof tmp); - psprintf_highlight(p, tmp + strlen(tmp), - sizeof tmp - strlen(tmp), "%-17s", p1WithAttrs); + len = strlen(tmp); + psprintf_highlight(p, tmp + len, sizeof tmp - len, + "%-17s", p1WithAttrs); } else { ret = snprintf(tmp, sizeof tmp, " %-17s", p1WithAttrs); @@ -1299,10 +1337,7 @@ com_who(int p, param_list param) sel_bits |= WHO_REGISTERED; break; case 'l': // Sort order - cmp_func = alpha_cmp; - sort_type = none; - break; - case 'A': // Sort order + case 'A': cmp_func = alpha_cmp; sort_type = none; break; @@ -1359,8 +1394,8 @@ com_who(int p, param_list param) count++; } - startpoint = floor((float) count * start_perc); - stoppoint = ceil((float) count * stop_perc) - 1; + startpoint = floorf((float) count * start_perc); + stoppoint = ceilf((float) count * stop_perc) - 1; num_who = 0; count = 0; @@ -1620,14 +1655,32 @@ com_unalias(int p, param_list param) pprintf(p, "You have no alias named '%s'.\n", param[0].val.word); } else { + bool removed = false; + const int sz = (int) ARRAY_SIZE(parray[0].alias_list); + rfree(parray[p].alias_list[al].comm_name); rfree(parray[p].alias_list[al].alias); + parray[p].alias_list[al].comm_name = NULL; + parray[p].alias_list[al].alias = NULL; + for (int i = al; i < parray[p].numAlias; i++) { + if (i >= sz || i + 1 >= sz) { + warnx("%s: overflowed array index read/write", + __func__); + break; + } + parray[p].alias_list[i].comm_name = parray[p].alias_list[i + 1].comm_name; parray[p].alias_list[i].alias = parray[p].alias_list[i + 1].alias; + removed = true; + } + + if (!removed) { + pprintf(p, "Remove error.\n"); + return COM_FAILED; } parray[p].numAlias--; @@ -1771,10 +1824,9 @@ FindAndShowFile(int p, param_list param, char *dir) { char *iwant, *filenames[1000]; int i; - static char nullify = '\0'; if (param[0].type == TYPE_NULL) { - iwant = &nullify; + iwant = NULL; } else { iwant = param[0].val.word; @@ -1788,8 +1840,9 @@ FindAndShowFile(int p, param_list param, char *dir) i = search_directory(dir, iwant, filenames, ARRAY_SIZE(filenames)); if (i == 0) { - pprintf(p, "No information available on \"%s\".\n", iwant); - } else if (i == 1 || !strcmp(*filenames, iwant)) { + pprintf(p, "No information available on \"%s\".\n", + (iwant ? iwant : "")); + } else if (i == 1 || !strcmp(*filenames, iwant ? iwant : "")) { if (psend_file(p, dir, *filenames)) { /* * We should never reach this unless the file @@ -1800,7 +1853,7 @@ FindAndShowFile(int p, param_list param, char *dir) "Thank you.\n"); } } else { - if (*iwant) + if (iwant && *iwant) pprintf(p, "Matches:\n"); display_directory(p, filenames, i); } @@ -1828,7 +1881,6 @@ com_mailsource(int p, param_list param) char fname[MAX_FILENAME_SIZE]; char subj[120]; int count; - static char nullify = '\0'; if (!parray[p].registered) { pprintf(p, "Only registered people can use the mailsource " @@ -1837,14 +1889,15 @@ com_mailsource(int p, param_list param) } if (param[0].type == TYPE_NULL) - iwant = &nullify; + iwant = NULL; else iwant = param[0].val.word; if ((count = search_directory(source_dir, iwant, buffer, ARRAY_SIZE(buffer))) == 0) { - pprintf(p, "Found no source file matching \"%s\".\n", iwant); - } else if ((count == 1) || !strcmp(iwant, *buffer)) { + pprintf(p, "Found no source file matching \"%s\".\n", + (iwant ? iwant : "")); + } else if ((count == 1) || !strcmp(iwant ? iwant : "", *buffer)) { snprintf(subj, sizeof subj, "FICS source file from server " "%s: %s", fics_hostname, @@ -1860,7 +1913,7 @@ com_mailsource(int p, param_list param) } else { pprintf(p, "Found %d source files matching that:\n", count); - if (*iwant) { + if (iwant && *iwant) { display_directory(p, buffer, count); } else { // this junk is to get *.c *.h char *s; @@ -1891,7 +1944,6 @@ com_mailhelp(int p, param_list param) char subj[120]; int count; int lang = parray[p].language; - static char nullify = '\0'; if (!parray[p].registered) { pprintf(p, "Only registered people can use the mailhelp " @@ -1900,7 +1952,7 @@ com_mailhelp(int p, param_list param) } if (param[0].type == TYPE_NULL) - iwant = &nullify; + iwant = NULL; else iwant = param[0].val.word; @@ -1921,8 +1973,9 @@ com_mailhelp(int p, param_list param) } if (count == 0) { - pprintf(p, "Found no help file matching \"%s\".\n", iwant); - } else if (count == 1 || !strcmp(*buffer, iwant)) { + pprintf(p, "Found no help file matching \"%s\".\n", + (iwant ? iwant : "")); + } else if (count == 1 || !strcmp(*buffer, iwant ? iwant : "")) { snprintf(subj, sizeof subj, "FICS help file from server %s: %s", fics_hostname, *buffer); |