Commit Diff


commit - 953390185b209ae9115228e09215cac61c008711
commit + 0725a74c6c03ed0c50b100026f7163eb7887ec38
blob - 1981c1422ee6ed11f45624514978c8a92fb8204e
blob + 6aaa66f66c88293911d6d0f23d1311ce4e8a8415
--- FICS/gamedb.c
+++ FICS/gamedb.c
@@ -1619,29 +1619,38 @@ game_save(int g)
 	return 0;
 }
 
-PRIVATE long int
-OldestHistGame(char *login)
+/* Helper function to validate login names for file path usage */
+static int
+is_valid_login_name(const char *login)
 {
-	FILE		*fp;
-	char		 pFile[MAX_FILENAME_SIZE] = { '\0' };
-	long int	 when;
-
-	/* Validate login to prevent path traversal and restrict to safe characters */
 	if (login == NULL || login[0] == '\0' ||
 	    strstr(login, "..") || strchr(login, '/') || strchr(login, '\\')) {
-		warnx("%s: invalid login value: '%s'", __func__, login);
-		return 0L;
+		return 0;
 	}
 	for (const char *p = login; *p; ++p) {
 		if (!((*p >= 'a' && *p <= 'z') ||
 		      (*p >= 'A' && *p <= 'Z') ||
 		      (*p >= '0' && *p <= '9') ||
 		      *p == '_')) {
-			warnx("%s: invalid character in login: '%s'", __func__, login);
-			return 0L;
+			return 0;
 		}
 	}
+	return 1;
+}
 
+PRIVATE long int
+OldestHistGame(char *login)
+{
+	FILE		*fp;
+	char		 pFile[MAX_FILENAME_SIZE] = { '\0' };
+	long int	 when;
+
+	/* Centralized validation of login */
+	if (!is_valid_login_name(login)) {
+		warnx("%s: invalid login value: '%s'", __func__, login);
+		return 0L;
+	}
+
 	msnprintf(pFile, sizeof pFile, "%s/player_data/%c/%s.%s", stats_dir,
 	    login[0], login, STATS_GAMES);
 
@@ -1735,31 +1744,13 @@ RemHist(char *who)
 
 			stolower(Opp);
 
-			if (strstr(Opp, "..") ||
-			    strchr(Opp, '/') ||
-			    strchr(Opp, '\\')) {
-				warnx("%s: invalid value: "
-				    "Opp = '%s' (skipping)", __func__, Opp);
+			/* Centralized validation: only allow safe login names */
+			if (!is_valid_login_name(Opp)) {
+				warnx("%s: invalid value: Opp = '%s' (skipping)", __func__, Opp);
 				iter_no++;
 				continue;
 			}
 
-			/*
-			 * Additional validation: only allow
-			 * alphanumeric and underscores
-			 */
-			for (const char *p = Opp; *p; ++p) {
-				if (!((*p >= 'a' && *p <= 'z') ||
-				      (*p >= 'A' && *p <= 'Z') ||
-				      (*p >= '0' && *p <= '9') ||
-				      *p == '_')) {
-					warnx("%s: invalid characters found: "
-					    "Opp = '%s' (skipping)", __func__,
-					    Opp);
-					goto next_iter;
-				}
-			}
-
 			oppWhen = OldestHistGame(Opp);
 
 			if (oppWhen > When || oppWhen <= 0L) {