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