diff options
Diffstat (limited to 'FICS/playerdb.c')
-rw-r--r-- | FICS/playerdb.c | 267 |
1 files changed, 192 insertions, 75 deletions
diff --git a/FICS/playerdb.c b/FICS/playerdb.c index f9e9410..1373630 100644 --- a/FICS/playerdb.c +++ b/FICS/playerdb.c @@ -35,12 +35,24 @@ Markus Uhlin 24/11/24 Fixed incorrect format strings Markus Uhlin 24/12/02 Made many improvements Markus Uhlin 24/12/04 Added player number checks + Markus Uhlin 25/02/11 Calc string length once + Markus Uhlin 25/03/22 Fixed overflowed return value in + player_search(). + Markus Uhlin 25/03/23 Fixed overflowed array index + read/write. + Markus Uhlin 25/03/29 player_remove_request: + fixed overflowed array index + read/write. + Markus Uhlin 25/04/02 add_to_list: added an upper + limit for the list size. + Markus Uhlin 25/04/06 Fixed Clang Tidy warnings. */ #include "stdinclude.h" #include "common.h" #include <err.h> +#include <errno.h> #include <stdint.h> #include "command.h" @@ -74,6 +86,21 @@ player_num_ok_chk(const int num) num < (int)ARRAY_SIZE(parray)); } +PUBLIC void +xrename(const char *fn, const char *name1, const char *name2) +{ + if (fn == NULL || name1 == NULL || name2 == NULL) { + errno = EINVAL; + warn("%s", __func__); + return; + } + + errno = 0; + + if (rename(name1, name2) != 0) + warn("%s: '%s' -> '%s'", fn, name1, name2); +} + PRIVATE int get_empty_slot(void) { @@ -385,10 +412,14 @@ add_to_list(FILE *fp, enum ListWhich lw, int *size, int p) #define SCAN_STR "%1023s" - if (*size <= 0) + if (*size <= 0 || *size > MAX_GLOBAL_LIST_SIZE) { +// warnx("%s: illegal list size (%d)", __func__, *size); return -2; + } + while ((*size)-- > 0 && fscanf(fp, SCAN_STR, buf) == 1) list_add(p, lw, buf); + return (*size <= 0 ? 0 : -1); } @@ -411,7 +442,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version) /* * Name */ - if (fgets(tmp2, sizeof tmp2, fp) != NULL && + if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT strcmp(tmp2, "NONE\n") != 0) { tmp2[strcspn(tmp2, "\n")] = '\0'; pp->name = xstrdup(tmp2); @@ -422,7 +453,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version) /* * Full name */ - if (fgets(tmp2, sizeof tmp2, fp) != NULL && + if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT strcmp(tmp2, "NONE\n") != 0) { tmp2[strcspn(tmp2, "\n")] = '\0'; pp->fullName = xstrdup(tmp2); @@ -433,7 +464,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version) /* * Password */ - if (fgets(tmp2, sizeof tmp2, fp) != NULL && + if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT strcmp(tmp2, "NONE\n") != 0) { tmp2[strcspn(tmp2, "\n")] = '\0'; pp->passwd = xstrdup(tmp2); @@ -444,7 +475,7 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version) /* * Email */ - if (fgets(tmp2, sizeof tmp2, fp) != NULL && + if (fgets(tmp2, sizeof tmp2, fp) != NULL && // NOLINT strcmp(tmp2, "NONE\n") != 0) { tmp2[strcspn(tmp2, "\n")] = '\0'; pp->emailAddress = xstrdup(tmp2); @@ -452,7 +483,9 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version) pp->emailAddress = NULL; } - if (fscanf(fp, "%d %d %d %d %d %d %jd %d %jd %d %d %d %d %d %d %jd %d %jd " + if (feof(fp) || + ferror(fp) || + fscanf(fp, "%d %d %d %d %d %d %jd %d %jd %d %d %d %d %d %d %jd %d %jd " "%d %d %d %d %d %d %jd %d %jd %d %d %d %d %d %d %jd %d %jd %d %d %d %d " "%d %d %jd %d %jd %u\n", &pp->s_stats.num, &pp->s_stats.win, &pp->s_stats.los, @@ -554,6 +587,23 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version) pp->timeOfReg = array[0]; pp->totalTime = array[1]; + if (pp->num_plan >= MAX_PLAN) { + warnx("Player %s is corrupt\nToo many plans (%d)", + parray[p].name, + pp->num_plan); + return; + } else if (pp->num_formula >= MAX_FORMULA) { + warnx("Player %s is corrupt\nToo many formulas (%d)", + parray[p].name, + pp->num_formula); + return; + } else if (pp->numAlias >= MAX_ALIASES) { + warnx("Player %s is corrupt\nToo many aliases (%d)", + parray[p].name, + pp->numAlias); + return; + } + if (pp->num_plan > 0) { for (i = 0; i < pp->num_plan; i++) { if (fgets(tmp2, sizeof tmp2, fp) == NULL) { @@ -618,14 +668,13 @@ ReadV1PlayerFmt(int p, player *pp, FILE *fp, char *file, int version) return; } - if (!(len = strlen(tmp2))) { + if (!strlen(tmp2)) { // XXX fprintf(stderr, "FICS: Error bad alias in " "file %s\n", file); i--; pp->numAlias--; } else { tmp2[strcspn(tmp2, "\n")] = '\0'; - tmp = tmp2; tmp = eatword(tmp2); *tmp = '\0'; tmp++; @@ -810,9 +859,11 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) * num_plan */ - parray[p].num_plan = atoi(value); - - if (parray[p].num_plan > 0) { + if ((parray[p].num_plan = atoi(value)) >= MAX_PLAN) { + warnx("%s: %s: too many plans (%d)", __func__, file, + parray[p].num_plan); + return -1; + } else if (parray[p].num_plan > 0) { for (i = 0; i < parray[p].num_plan; i++) { if (fgets(tmp, sizeof tmp, fp) == NULL) { @@ -834,15 +885,19 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) xstrdup(tmp) : NULL); } } + } else { + /* null */; } } else if (!strcmp(attr, "num_formula:")) { /* * num_formula */ - parray[p].num_formula = atoi(value); - - if (parray[p].num_formula > 0) { + if ((parray[p].num_formula = atoi(value)) >= MAX_FORMULA) { + warnx("%s: %s: too many formulas (%d)", __func__, file, + parray[p].num_formula); + return -1; + } else if (parray[p].num_formula > 0) { for (i = 0; i < parray[p].num_formula; i++) { if (fgets(tmp, sizeof tmp, fp) == NULL) { warnx("%s: bad formula: feof %s", @@ -863,6 +918,8 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) xstrdup(tmp) : NULL); } } + } else { + /* null */; } } else if (!strcmp(attr, "formula:")) { /* @@ -875,9 +932,11 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) * num_alias */ - parray[p].numAlias = atoi(value); - - if (parray[p].numAlias > 0) { + if ((parray[p].numAlias = atoi(value)) >= MAX_ALIASES) { + warnx("%s: %s: too many aliases (%d)", __func__, file, + parray[p].numAlias); + return -1; + } else if (parray[p].numAlias > 0) { for (i = 0; i < parray[p].numAlias; i++) { if (fgets(tmp, sizeof tmp, fp) == NULL) { warnx("%s: bad alias: feof %s", @@ -885,7 +944,7 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) return -1; } - if (!(len = strlen(tmp))) { + if (!strlen(tmp)) { // XXX fprintf(stderr, "FICS: Error bad alias " "in file %s\n", file); i--; @@ -904,13 +963,21 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) xstrdup(tmp1); } } + } else { + /* null */; } } else if (!strcmp(attr, "num_censor:")) { /* * num_censor */ - i = atoi(value); + if ((i = atoi(value)) < 0) { + warnx("%s: num censor negative", __func__); + return -1; + } else if (i > MAX_CENSOR) { + warnx("%s: num censor too large", __func__); + return -1; + } while (i--) { if (fgets(tmp, sizeof tmp, fp) == NULL) { @@ -929,7 +996,13 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) } } } else if (!strcmp(attr, "num_notify:")) { - i = atoi(value); + if ((i = atoi(value)) < 0) { + warnx("%s: num notify negative", __func__); + return -1; + } else if (i > MAX_NOTIFY) { + warnx("%s: num notify too large", __func__); + return -1; + } while (i--) { if (fgets(tmp, sizeof tmp, fp) == NULL) { @@ -948,7 +1021,10 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) } } } else if (!strcmp(attr, "num_noplay:")) { - i = atoi(value); + if ((i = atoi(value)) < 0) { + warnx("%s: num noplay negative", __func__); + return -1; + } while (i--) { if (fgets(tmp, sizeof tmp, fp) == NULL) { @@ -967,7 +1043,10 @@ got_attr_value_player(int p, char *attr, char *value, FILE *fp, char *file) } } } else if (!strcmp(attr, "num_gnotify:")) { - i = atoi(value); + if ((i = atoi(value)) < 0) { + warnx("%s: num gnotify negative", __func__); + return -1; + } while (i--) { if (fgets(tmp, sizeof tmp, fp) == NULL) { @@ -1023,7 +1102,7 @@ player_read(int p, char *name) } if (line[0] == 'v') - sscanf(line, "%*c %d", &version); + (void)sscanf(line, "%*c %d", &version); if (version > 0) // Quick method: ReadV1PlayerFmt(p, &parray[p], fp, fname, version); else { // Do it the old SLOW way @@ -1103,7 +1182,7 @@ player_markdeleted(int p) parray[p].login[0], parray[p].login); snprintf(fname2, sizeof fname2, "%s/%c/%s.delete", player_dir, parray[p].login[0], parray[p].login); - rename(fname, fname2); + xrename(__func__, fname, fname2); if ((fp = fopen(fname2, "a")) != NULL) { // Touch the file fprintf(fp, "\n"); @@ -1282,10 +1361,13 @@ player_find_part_login(char *name) { int found = -1; int i; + size_t namelen; if ((i = player_find_bylogin(name)) >= 0) return i; + namelen = strlen(name); + for (i = 0; i < p_num; i++) { if (parray[i].status == PLAYER_EMPTY || parray[i].status == PLAYER_LOGIN || @@ -1295,7 +1377,7 @@ player_find_part_login(char *name) if (!parray[i].login) continue; - if (!strncmp(parray[i].login, name, strlen(name))) { + if (!strncmp(parray[i].login, name, namelen)) { if (found >= 0) /* Ambiguous */ return -2; found = i; @@ -1581,7 +1663,7 @@ player_lastconnect(int p) char loginName[MAX_LOGIN_NAME]; int inout, registered; int ret, too_long; - long int lval; + long int lval = 0; time_t last = 0; ret = snprintf(fname, sizeof fname, "%s/player_data/%c/%s.%s", @@ -1766,17 +1848,26 @@ player_new_pendto(int p) PUBLIC int player_remove_pendto(int p, int p1, int type) { - int w; + bool removed = false; + int w; if ((w = player_find_pendto(p, p1, type)) < 0) return -1; - for (; w < (parray[p].num_to - 1); w++) + for (; w < (parray[p].num_to - 1); w++) { + if (w + 1 >= (int)ARRAY_SIZE(parray[0].p_to_list)) { + warnx("%s: overflowed array index write", __func__); + break; + } + parray[p].p_to_list[w] = parray[p].p_to_list[w + 1]; + removed = true; + } - parray[p].num_to = (parray[p].num_to - 1); + UNUSED_VAR(removed); + parray[p].num_to -= 1; - return 0; + return (0); } PUBLIC int @@ -1820,17 +1911,26 @@ player_new_pendfrom(int p) PUBLIC int player_remove_pendfrom(int p, int p1, int type) { - int w; + bool removed = false; + int w; if ((w = player_find_pendfrom(p, p1, type)) < 0) return -1; - for (; w < (parray[p].num_from - 1); w++) + for (; w < (parray[p].num_from - 1); w++) { + if (w + 1 >= (int)ARRAY_SIZE(parray[0].p_from_list)) { + warnx("%s: overflowed array index write", __func__); + break; + } + parray[p].p_from_list[w] = parray[p].p_from_list[w + 1]; + removed = true; + } - parray[p].num_from = (parray[p].num_from - 1); + UNUSED_VAR(removed); + parray[p].num_from -= 1; - return 0; + return (0); } PUBLIC int @@ -1865,28 +1965,44 @@ player_add_request(int p, int p1, int type, int param) PUBLIC int player_remove_request(int p, int p1, int type) { - int to = 0, from = 0; + bool removed; + int to = 0, from = 0; - while (to != -1) { - if ((to = player_find_pendto(p, p1, type)) != -1) { - for (; to < parray[p].num_to - 1; to++) { - parray[p].p_to_list[to] = - parray[p].p_to_list[to + 1]; + while (to != -1 && (to = player_find_pendto(p, p1, type)) != -1) { + removed = false; + + for (; to < parray[p].num_to - 1; to++) { + if (to + 1 >= (int)ARRAY_SIZE(parray[0].p_to_list)) { + warnx("%s: overflowed array index read/write", + __func__); + break; } - parray[p].num_to = (parray[p].num_to - 1); + parray[p].p_to_list[to] = parray[p].p_to_list[to + 1]; + removed = true; } + + UNUSED_VAR(removed); + parray[p].num_to -= 1; } - while (from != -1) { - if ((from = player_find_pendfrom(p1, p, type)) != -1) { - for (; from < parray[p1].num_from - 1; from++) { - parray[p1].p_from_list[from] = - parray[p1].p_from_list[from + 1]; + while (from != -1 && (from = player_find_pendfrom(p1, p, type)) != -1) { + removed = false; + + for (; from < parray[p1].num_from - 1; from++) { + if (from + 1 >= (int)ARRAY_SIZE(parray[0].p_from_list)) { + warnx("%s: overflowed array index read/write", + __func__); + break; } - parray[p1].num_from = (parray[p1].num_from - 1); + parray[p1].p_from_list[from] = + parray[p1].p_from_list[from + 1]; + removed = true; } + + UNUSED_VAR(removed); + parray[p1].num_from -= 1; } if ((type == PEND_ALL || type == PEND_MATCH) && parray[p].partner >= 0) @@ -2254,7 +2370,6 @@ player_goto_next_board(int p) on = parray[p].simul_info.onBoard; start = on; - g = -1; do { on++; @@ -2283,7 +2398,6 @@ player_goto_prev_board(int p) on = parray[p].simul_info.onBoard; start = on; - g = -1; do { --on; @@ -2722,7 +2836,7 @@ player_show_messages(int p) PUBLIC int ShowMsgsBySender(int p, param_list param) { - int nFrom, nTo; + int nFrom = -1, nTo = -1; int p1, connected; textlist *Head; @@ -2735,8 +2849,6 @@ ShowMsgsBySender(int p, param_list param) return -1; /* no need to disconnect */ } - nFrom = nTo = -1; - if (p != p1) { if ((nTo = LoadMsgs(p1, p + 1, &Head)) <= 0) { pprintf(p, "%s has no messages from you.\n", @@ -2825,8 +2937,11 @@ player_search(int p, char *name) int p1, count; // Exact match with connected player? - if ((p1 = player_find_bylogin(name)) >= 0) + if ((p1 = player_find_bylogin(name)) >= 0) { + if (p1 + 1 >= (int)ARRAY_SIZE(parray)) + return 0; return (p1 + 1); + } // Exact match with registered player? snprintf(pdir, sizeof pdir, "%s/%c", player_dir, name[0]); @@ -2882,7 +2997,7 @@ player_kill(char *name) name); snprintf(fname2, sizeof fname2, "%s/%c/.rem.%s", player_dir, name[0], name); - rename(fname, fname2); + xrename(__func__, fname, fname2); RemHist(name); @@ -2890,25 +3005,25 @@ player_kill(char *name) stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.games", stats_dir, name[0], name); - rename(fname, fname2); + xrename(__func__, fname, fname2); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.comments", stats_dir, name[0], name); - rename(fname, fname2); + xrename(__func__, fname, fname2); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.logons", stats_dir, name[0], name); - rename(fname, fname2); + xrename(__func__, fname, fname2); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.messages", stats_dir, name[0], name); - rename(fname, fname2); + xrename(__func__, fname, fname2); return 0; } @@ -2923,31 +3038,31 @@ player_rename(char *name, char *newname) name); snprintf(fname2, sizeof fname2, "%s/%c/%s", player_dir, newname[0], newname); - rename(fname, fname2); + xrename(__func__, fname, fname2); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.games", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.games", stats_dir, newname[0], newname); - rename(fname, fname2); + xrename(__func__, fname, fname2); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.comments", stats_dir, newname[0], newname); - rename(fname, fname2); + xrename(__func__, fname, fname2); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.logons", stats_dir, newname[0], newname); - rename(fname, fname2); + xrename(__func__, fname, fname2); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/%s.messages", stats_dir, newname[0], newname); - rename(fname, fname2); + xrename(__func__, fname, fname2); return 0; } @@ -2962,31 +3077,31 @@ player_raise(char *name) name[0], name); snprintf(fname2, sizeof fname2, "%s/%c/.rem.%s", player_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.games", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.games", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.comments", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.logons", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages", stats_dir, name[0], name); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.messages", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); return 0; } @@ -3001,31 +3116,31 @@ player_reincarn(char *name, char *newname) newname[0], newname); snprintf(fname2, sizeof fname2, "%s/%c/.rem.%s", player_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.games", stats_dir, newname[0], newname); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.games", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.comments", stats_dir, newname[0], newname); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.comments", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.logons", stats_dir, newname[0], newname); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.logons", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); snprintf(fname, sizeof fname, "%s/player_data/%c/%s.messages", stats_dir, newname[0], newname); snprintf(fname2, sizeof fname2, "%s/player_data/%c/.rem.%s.messages", stats_dir, name[0], name); - rename(fname2, fname); + xrename(__func__, fname2, fname); return 0; } @@ -3067,11 +3182,13 @@ player_add_comment(int p_by, int p_to, char *comment) PUBLIC int player_show_comments(int p, int p1) { - char fname[MAX_FILENAME_SIZE]; + char fname[MAX_FILENAME_SIZE] = { '\0' }; snprintf(fname, sizeof fname, "%s/player_data/%c/%s.%s", stats_dir, parray[p1].login[0], parray[p1].login, "comments"); - psend_file(p, NULL, fname); + + if (psend_file(p, NULL, fname) == -1) + warnx("%s: psend_file() error", __func__); return 0; } |