aboutsummaryrefslogtreecommitdiffstats
path: root/FICS/comproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'FICS/comproc.c')
-rw-r--r--FICS/comproc.c127
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, &registered, 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);