diff options
Diffstat (limited to 'FICS/ratings.c')
-rw-r--r-- | FICS/ratings.c | 157 |
1 files changed, 111 insertions, 46 deletions
diff --git a/FICS/ratings.c b/FICS/ratings.c index 3cd8d85..e445c51 100644 --- a/FICS/ratings.c +++ b/FICS/ratings.c @@ -28,6 +28,11 @@ Markus Uhlin 24/05/20 Fixed clang warnings Markus Uhlin 24/07/07 Return value checking of the fscanf() calls. + Markus Uhlin 24/11/27 Added sscanf() width spec and + fixed ignored retvals. + Markus Uhlin 24/11/28 Added null checks + Markus Uhlin 25/03/16 Fixed use of 32-bit 'time_t'. + Markus Uhlin 25/04/06 Fixed Clang Tidy warnings. */ #include "stdinclude.h" @@ -35,6 +40,8 @@ #include <err.h> #include <errno.h> +#include <limits.h> +#include <stdint.h> #include "command.h" #include "comproc.h" @@ -342,49 +349,52 @@ load_ratings(void) return; } - for (int i = 0; i < MAXHIST; i++) { - int ret, errno_save; + for (int i = 0; i < MAXHIST && !feof(fp) && !ferror(fp); i++) { + int ret; sHist[i] = bHist[i] = wHist[i] = lHist[i] = 0; - errno = 0; ret = fscanf(fp, "%d %d %d %d", &sHist[i], &bHist[i], &wHist[i], &lHist[i]); - errno_save = errno; if (ret != 4) { - if (feof(fp) || ferror(fp)) - break; - errno = errno_save; - warn("%s: too few items assigned (iteration: %d)", - __func__, i); + warnx("%s: %s: too few items assigned (iteration: %d)", + __func__, fname, i); + fclose(fp); + return; } } + if (ferror(fp)) { + warnx("%s: %s: the error indicator is set", __func__, fname); + fclose(fp); + return; + } + fclose(fp); - if (Rs_count) { - Ratings_S_StdDev = sqrt(Rs_S / Rs_count); + if (Rs_count != 0) { + Ratings_S_StdDev = sqrt(Rs_S / Rs_count); // NOLINT Ratings_S_Average = (Rs_total / (double)Rs_count); } else { Ratings_S_StdDev = 0; Ratings_S_Average = 0; } - if (Rb_count) { - Ratings_B_StdDev = sqrt(Rb_S / Rb_count); + if (Rb_count != 0) { + Ratings_B_StdDev = sqrt(Rb_S / Rb_count); // NOLINT Ratings_B_Average = (Rb_total / (double)Rb_count); } else { Ratings_B_StdDev = 0; Ratings_B_Average = 0; } - if (Rw_count) { - Ratings_W_StdDev = sqrt(Rw_S / Rw_count); + if (Rw_count != 0) { + Ratings_W_StdDev = sqrt(Rw_S / Rw_count); // NOLINT Ratings_W_Average = (Rw_total / (double)Rw_count); } else { Ratings_W_StdDev = 0; Ratings_W_Average = 0; } - if (Rl_count) { - Ratings_L_StdDev = sqrt(Rl_S / Rl_count); + if (Rl_count != 0) { + Ratings_L_StdDev = sqrt(Rl_S / Rl_count); // NOLINT Ratings_L_Average = (Rl_total / (double)Rl_count); } else { Ratings_L_StdDev = 0; @@ -751,7 +761,7 @@ GE(int r, int rr, double ss, double *fss) } PRIVATE double -current_sterr(double s, int t) +current_sterr(double s, int64_t t) { if (t < 0) t = 0; // this shouldn't happen @@ -766,15 +776,16 @@ current_sterr(double s, int t) * ics.onenet.net, if not elsewhere. */ PUBLIC void -rating_sterr_delta(int p1, int p2, int type, int gtime, int result, +rating_sterr_delta(int p1, int p2, int type, time_t gtime, int result, int *deltarating, double *newsterr) { double E, fs2, denominator, GK, w; // Parts of fancy formulas double delta, sigma; // Results to return double s1, s2; - int t1, r1, t2, r2; // Initial sterrs and ratings + int r1, r2; // Initial sterrs and ratings statistics *p1_stats; statistics *p2_stats; + time_t t1, t2; if (type == TYPE_BLITZ) { p1_stats = &parray[p1].b_stats; @@ -863,12 +874,12 @@ PUBLIC int rating_update(int g) { double wSigma, bSigma; - int gtime; int inprogress = (g == parray[garray[g].black].game); int wDelta, bDelta; int wRes, bRes; statistics *b_stats; statistics *w_stats; + time_t gtime; /* * If this is adjudication of stored game - be quiet about @@ -1297,6 +1308,18 @@ com_statistics(int p, param_list param) return COM_OK; } +/* + * Return the difference of 'a - b' + */ +PUBLIC int +int_diff(const char *fn, const int a, const int b) +{ + if ((b > 0 && a < INT_MIN + b) || + (b < 0 && a > INT_MAX + b)) + errx(1, "%s: integer overflow (%d - %d)", fn, a, b); + return (a - b); +} + PUBLIC int com_fixrank(int p, param_list param) { @@ -1339,8 +1362,16 @@ DisplayRank(int p, param_list param, int showComputers) DisplayTargetRank(p, parray[p].name, show, showComputers); return COM_OK; } else if (isdigit(param[0].val.word[0])) { + int ret; + + start = 0; end = -1; - sscanf(param[0].val.word, "%d-%d", &start, &end); + ret = sscanf(param[0].val.word, "%d-%d", &start, &end); + + if (ret != 2) { +// warnx("%s: sscanf() == %d", __func__, ret); + return COM_FAILED; + } if (end > 0 && (param[1].type != TYPE_NULL)) show = ShowFromString(param[1].val.word); @@ -1463,9 +1494,15 @@ UpdateRank(int type, char *addName, statistics *sNew, char *delName) return; } - while (fgets(line, MAX_RANK_LINE - 1, fp)) { - sscanf(line, "%s %d %d %d", login, &sCur.rating, &sCur.num, - &comp); + while (fgets(line, sizeof line, fp) != NULL) { + _Static_assert(ARRAY_SIZE(login) > 19, "'login' too small"); + + if (sscanf(line, "%19s %d %d %d", login, + &sCur.rating, &sCur.num, &comp) != 4) { + warnx("%s: %s: sscanf() error -- too few items", + __func__, RankFile); + continue; + } if (delName != NULL && !strcasecmp(delName, login)) { // Kill name. @@ -1533,9 +1570,15 @@ GetRank(FILE *fp, char *target, int countComp) int nGames, is_computer; int playerFound = 0; - while (fgets(line, MAX_RANK_LINE - 1, fp) && + while (fgets(line, sizeof line, fp) != NULL && !playerFound) { - sscanf(line, "%s %*d %d %d", login, &nGames, &is_computer); + _Static_assert(ARRAY_SIZE(login) > 19, "'login' too small"); + + if (sscanf(line, "%19s %*d %d %d", login, &nGames, &is_computer) + != 1) { +// warnx("%s: sscanf() error", __func__); + continue; + } if ((playerFound = !strcasecmp(login, target)) || CountRankLine(countComp, login, nGames, is_computer)) @@ -1556,18 +1599,33 @@ PositionFilePtr(FILE *fp, int count, int *last, int *nTied, int showComp) return; rating = nGames = is_computer = 0; + errno = 0; rewind(fp); + if (errno) { + warn("%s: rewind", __func__); + return; + } for (int i = 1; i < count; i++) { do { - fgets(line, MAX_RANK_LINE - 1, fp); + _Static_assert(ARRAY_SIZE(login) > 19, + "'login' too small"); - if (feof(fp)) + if (feof(fp) || ferror(fp) || + fgets(line, sizeof line, fp) == NULL) break; - sscanf(line, "%s %d %d %d", login, &rating, &nGames, - &is_computer); + else if (sscanf(line, "%19s %d %d %d", login, &rating, + &nGames, &is_computer) != 4) { + warnx("%s: sscanf() error", __func__); + break; + } } while (!CountRankLine(showComp, login, nGames, is_computer)); + if (ferror(fp)) { + warnx("%s: the error indicator is set", __func__); + return; + } + if (rating != *last) { *nTied = 1; *last = rating; @@ -1586,19 +1644,26 @@ ShowRankEntry(int p, FILE *fp, int count, int comp, char *target, // XXX rating = 0; - findable = (count > 0 && !feof(fp)); + findable = (count > 0 && !feof(fp) && !ferror(fp)); nGames = 0; is_comp = 0; if (findable) { do { - fgets(newLine, MAX_RANK_LINE - 1, fp); - - if (feof(fp)) { + if (fgets(newLine, sizeof newLine, fp) == NULL || + feof(fp) || + ferror(fp)) { findable = 0; } else if (newLine[0] != '\0') { - sscanf(newLine, "%s %d %d %d", login, &rating, - &nGames, &is_comp); + _Static_assert(ARRAY_SIZE(login) > 19, + "Assertion has failed"); + + if (sscanf(newLine, "%19s %d %d %d", login, + &rating, &nGames, &is_comp) != 4) { + warnx("%s: sscanf() error", __func__); + findable = 0; + break; + } } else { login[0] = '\0'; } @@ -1675,21 +1740,21 @@ ShowRankLines(int p, FILE *fb, FILE *fs, FILE *fw, int bCount, int sCount, if (n <= 0) return 0; - if (CheckFlag(show, SHOW_BLITZ)) { + if (fb != NULL && CheckFlag(show, SHOW_BLITZ)) { PositionFilePtr(fb, bCount, &lastBlitz, &nTiedBlitz, showComp); if (feof(fb)) ClearFlag(show, SHOW_BLITZ); } - if (CheckFlag(show, SHOW_STANDARD)) { + if (fs != NULL && CheckFlag(show, SHOW_STANDARD)) { PositionFilePtr(fs, sCount, &lastStd, &nTiedStd, showComp); if (feof(fs)) ClearFlag(show, SHOW_STANDARD); } - if (CheckFlag(show, SHOW_WILD)) { + if (fw != NULL && CheckFlag(show, SHOW_WILD)) { PositionFilePtr(fw, wCount, &lastWild, &nTiedWild, showComp); if (feof(fw)) @@ -1702,15 +1767,15 @@ ShowRankLines(int p, FILE *fb, FILE *fs, FILE *fw, int bCount, int sCount, DisplayRankHead(p, show); for (int i = 0; i < n && show; i++) { - if (CheckFlag(show, SHOW_BLITZ)) { + if (fb != NULL && CheckFlag(show, SHOW_BLITZ)) { bCount += ShowRankEntry(p, fb, bCount, showComp, target, &lastBlitz, &nTiedBlitz); } - if (CheckFlag(show, SHOW_STANDARD)) { + if (fs != NULL && CheckFlag(show, SHOW_STANDARD)) { sCount += ShowRankEntry(p, fs, sCount, showComp, target, &lastStd, &nTiedStd); } - if (CheckFlag(show, SHOW_WILD)) { + if (fw != NULL && CheckFlag(show, SHOW_WILD)) { wCount += ShowRankEntry(p, fw, wCount, showComp, target, &lastWild, &nTiedWild); } @@ -1776,9 +1841,9 @@ DisplayTargetRank(int p, char *target, int show, int showComp) numAbove = CountAbove(numToShow, blitzRank, stdRank, wildRank, show); - blitzCount = (blitzRank - numAbove); - stdCount = (stdRank - numAbove); - wildCount = (wildRank - numAbove); + blitzCount = int_diff(__func__, blitzRank, numAbove); + stdCount = int_diff(__func__, stdRank, numAbove); + wildCount = int_diff(__func__, wildRank, numAbove); ShowRankLines(p, fb, fs, fw, blitzCount, stdCount, wildCount, numToShow, showComp, show, target); |