diff options
Diffstat (limited to 'FICS/gamedb.c')
-rw-r--r-- | FICS/gamedb.c | 110 |
1 files changed, 74 insertions, 36 deletions
diff --git a/FICS/gamedb.c b/FICS/gamedb.c index 572abf5..7f5e645 100644 --- a/FICS/gamedb.c +++ b/FICS/gamedb.c @@ -36,6 +36,15 @@ Markus Uhlin 24/11/25 Null checks Markus Uhlin 24/12/02 Fixed bugs and ignored function return values. + Markus Uhlin 25/03/18 Fixed unchecked return values + Markus Uhlin 25/03/25 ReadGameState: fixed truncated + stdio return value. + Markus Uhlin 25/04/01 Fixed call of risky function + Markus Uhlin 25/04/01 ReadV1GameFmt: guard num half + moves. + Markus Uhlin 25/04/06 Fixed Clang Tidy warnings. + Markus Uhlin 25/07/28 Fixed use of potentially + dangerous functions. */ #include "stdinclude.h" @@ -43,6 +52,7 @@ #include <err.h> #include <errno.h> +#include <limits.h> #include "command.h" #include "config.h" @@ -555,12 +565,12 @@ EndSym(int g) PUBLIC char * movesToString(int g, int pgn) { + char tmp[160] = { '\0' }; char *serv_loc = SERVER_LOCATION; char *serv_name = SERVER_NAME; - char tmp[160] = { '\0' }; int i, col; int wr, br; - struct tm *tm_ptr = NULL; + struct tm v_tm = {0}; time_t curTime; wr = garray[g].white_rating; @@ -578,14 +588,16 @@ movesToString(int g, int pgn) serv_name, serv_loc); - if ((tm_ptr = localtime(&curTime)) != NULL) { + errno = 0; + + if (localtime_r(&curTime, &v_tm) != NULL) { strftime(tmp, sizeof(tmp), "[Date \"%Y.%m.%d\"]\n" "[Time \"%H:%M:%S\"]\n", - tm_ptr); + &v_tm); mstrlcat(gameString, tmp, sizeof gameString); } else - warn("%s: localtime", __func__); + warn("%s: localtime_r()", __func__); msnprintf(tmp, sizeof tmp, "[Round \"-\"]\n" @@ -660,11 +672,13 @@ movesToString(int g, int pgn) mstrlcat(gameString, tmp, sizeof gameString); mstrlcat(gameString, "--- ", sizeof gameString); - if ((tm_ptr = localtime(&curTime)) != NULL) { - strftime(tmp, sizeof tmp, "%Y.%m.%d %H:%M:%S", tm_ptr); + errno = 0; + + if (localtime_r(&curTime, &v_tm) != NULL) { + strftime(tmp, sizeof tmp, "%Y.%m.%d %H:%M:%S", &v_tm); mstrlcat(gameString, tmp, sizeof gameString); } else - warn("%s: localtime", __func__); + warn("%s: localtime_r()", __func__); if (garray[g].rated) { mstrlcat(gameString, "\nRated ", sizeof gameString); @@ -974,8 +988,8 @@ WriteGameState(FILE *fp, game_state_t *gs) PRIVATE int ReadGameState(FILE *fp, game_state_t *gs, int version) { - char pieceChar; int i, j; + int pieceChar; int wkmoved, wqrmoved, wkrmoved, bkmoved, bqrmoved, bkrmoved; if (version == 0) { @@ -986,11 +1000,12 @@ ReadGameState(FILE *fp, game_state_t *gs, int version) } } } else { - getc(fp); /* Skip past a newline. */ + (void) getc(fp); /* Skip past a newline. */ for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { - pieceChar = getc(fp); + if ((pieceChar = getc(fp)) == EOF) + return -1; gs->board[i][j] = CharToPiece(pieceChar); } } @@ -1059,10 +1074,16 @@ got_attr_value(int g, char *attr, char *value, FILE *fp, char *file) } else if (!strcmp(attr, "type:")) { garray[g].type = atoi(value); } else if (!strcmp(attr, "halfmoves:")) { - garray[g].numHalfMoves = atoi(value); - - if (garray[g].numHalfMoves == 0) + if ((garray[g].numHalfMoves = atoi(value)) == 0) return 0; + else if (garray[g].numHalfMoves < 0 || + (size_t)garray[g].numHalfMoves > INT_MAX / sizeof(move_t)) { + warnx("%s: num half moves out-of-bounds (%d)", __func__, + garray[g].numHalfMoves); + return -1; + } else { + /* null */; + } garray[g].moveListSize = garray[g].numHalfMoves; garray[g].moveList = reallocarray(NULL, sizeof(move_t), @@ -1267,8 +1288,10 @@ ReadV1GameFmt(game *g, FILE *fp, const char *file, int version) _Static_assert(17 < ARRAY_SIZE(g->black_name), "Unexpected array size"); ret[0] = fscanf(fp, "%17s %17s", g->white_name, g->black_name); - ret[1] = fscanf(fp, "%d %d", &g->white_rating, &g->black_rating); - ret[2] = fscanf(fp, "%d %d %d %d", + ret[1] = fscanf(fp, "%d %d", // NOLINT + &g->white_rating, + &g->black_rating); + ret[2] = fscanf(fp, "%d %d %d %d", // NOLINT &g->wInitTime, &g->wIncrement, &g->bInitTime, @@ -1311,10 +1334,16 @@ ReadV1GameFmt(game *g, FILE *fp, const char *file, int version) ret[0] = fscanf(fp, "%d %d %d %d", &g->private, &g->type, &g->rated, &g->clockStopped); - ret[1] = fscanf(fp, "%d", &g->numHalfMoves); + ret[1] = fscanf(fp, "%d", &g->numHalfMoves); // NOLINT if (ret[0] != 4 || ret[1] != 1) { warnx("%s: fscanf error: %s", __func__, file); return -1; + } else if (g->numHalfMoves < 0 || (size_t)g->numHalfMoves > + INT_MAX / sizeof(move_t)) { + warnx("%s: warning: num half moves out-of-bounds (%d)", + __func__, + g->numHalfMoves); + return -1; } if (ReadV1Moves(g, fp) != 0) { @@ -1625,10 +1654,9 @@ RemoveHistGame(char *file, int maxlines) char Opponent[MAX_LOGIN_NAME + 1] = { '\0' }; char line[MAX_LINE_SIZE] = { '\0' }; int count = 0; - long int When, oppWhen; + long int When = 0, oppWhen = 0; _Static_assert(20 < ARRAY_SIZE(Opponent), "Not within bounds"); - When = oppWhen = 0; if ((fp = fopen(file, "r")) == NULL) { return; @@ -1840,38 +1868,46 @@ write_g_out(int g, char *file, int maxlines, int isDraw, char *EndSymbol, * Find from_spot in journal list - return 0 if corrupted */ PUBLIC int -journal_get_info(int p, char from_spot, char *WhiteName, int *WhiteRating, - char *BlackName, int *BlackRating, char *type, int *t, int *i, char *eco, - char *ending, char *result, char *fname) +journal_get_info(struct JGI_context *ctx, const char *fname) { FILE *fp; char count; if ((fp = fopen(fname, "r")) == NULL) { fprintf(stderr, "Corrupt journal file! %s\n", fname); - pprintf(p, "The journal file is corrupt! See an admin.\n"); + pprintf(ctx->p, "The journal file is corrupt! See an admin.\n"); return 0; } while (!feof(fp)) { - if (fscanf(fp, "%c %s %d %s %d %s %d %d %s %s %s\n", + _Static_assert(ARRAY_SIZE(ctx->WhiteName) > 20, + "'WhiteName' too small"); + _Static_assert(ARRAY_SIZE(ctx->BlackName) > 20, + "'BlackName' too small"); + + _Static_assert(ARRAY_SIZE(ctx->type) > 99, "'type' too small"); + _Static_assert(ARRAY_SIZE(ctx->eco) > 99, "'eco' too small"); + _Static_assert(ARRAY_SIZE(ctx->ending) > 99, "'ending' too small"); + _Static_assert(ARRAY_SIZE(ctx->result) > 99, "'result' too small"); + + if (fscanf(fp, "%c %20s %d %20s %d %99s %d %d %99s %99s %99s\n", &count, - WhiteName, &(*WhiteRating), - BlackName, &(*BlackRating), - type, - &(*t), &(*i), - eco, - ending, - result) != 11) { + ctx->WhiteName, &ctx->WhiteRating, + ctx->BlackName, &ctx->BlackRating, + ctx->type, + &ctx->t, &ctx->i, + ctx->eco, + ctx->ending, + ctx->result) != 11) { fprintf(stderr, "FICS: Error in journal info format. " "%s\n", fname); - pprintf(p, "The journal file is corrupt! Error in " + pprintf(ctx->p, "The journal file is corrupt! Error in " "internal format.\n"); fclose(fp); return 0; } - if (tolower(count) == from_spot) { + if (tolower(count) == ctx->from_spot) { fclose(fp); return 1; } @@ -1922,7 +1958,7 @@ addjournalitem(int p, char count2, char *WhiteName2, int WhiteRating2, ending2, result2); fclose(fp2); - rename(fname2, fname); + xrename(__func__, fname2, fname); return; } else { _Static_assert(ARRAY_SIZE(WhiteName) > 19, @@ -1996,7 +2032,7 @@ addjournalitem(int p, char count2, char *WhiteName2, int WhiteRating2, fclose(fp); fclose(fp2); - rename(fname2, fname); + xrename(__func__, fname2, fname); } PUBLIC int @@ -2093,6 +2129,8 @@ pgames(int p, int p1, char *fname) _Static_assert(ARRAY_SIZE(ending) > 99, "'ending' too small"); while (!feof(fp)) { + char tbuf[30] = { '\0' }; + if (fscanf(fp, "%d %1s %d %1s %d %19s %99s %d %d %d %d %99s " "%99s %ld\n", &count, result, &MyRating, MyColor, @@ -2115,7 +2153,7 @@ pgames(int p, int p1, char *fname) count, result, MyRating, MyColor, OppRating, OppName, type, (wt / 600), (wi / 10), eco, ending, - ctime(&t)); + ctime_r(&t, tbuf) != NULL ? &tbuf[0] : ""); } fclose(fp); |