From 0d233d4e77108230fd0abc3061605ddd669dbb84 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Mon, 10 Jul 2023 01:28:37 +0300 Subject: [PATCH 18/18] Check that team_new() has found a free team slot See osdn #48290 Signed-off-by: Marko Lindqvist --- client/packhand.c | 2 ++ common/team.c | 34 +++++++++++++++++++--------------- common/team.h | 17 ++++++++++------- server/savegame/savegame2.c | 1 + server/savegame/savegame3.c | 1 + server/stdinhand.c | 7 ++++++- 6 files changed, 39 insertions(+), 23 deletions(-) diff --git a/client/packhand.c b/client/packhand.c index 55e41130c8..1862ebbc27 100644 --- a/client/packhand.c +++ b/client/packhand.c @@ -2509,6 +2509,8 @@ void handle_player_info(const struct packet_player_info *pinfo) /* Team. */ tslot = team_slot_by_number(pinfo->team); fc_assert(NULL != tslot); + + /* Should never fail when slot given is not NULL */ team_add_player(pplayer, team_new(tslot)); pnation = nation_by_number(pinfo->nation); diff --git a/common/team.c b/common/team.c index 52a9df5f5f..59a534e3be 100644 --- a/common/team.c +++ b/common/team.c @@ -320,7 +320,7 @@ struct team *team_new(struct team_slot *tslot) fc_assert_ret_val(team_slots_initialised(), NULL); - if (NULL == tslot) { + if (tslot == NULL) { team_slots_iterate(aslot) { if (!team_slot_is_used(aslot)) { tslot = aslot; @@ -328,8 +328,10 @@ struct team *team_new(struct team_slot *tslot) } } team_slots_iterate_end; - fc_assert_ret_val(NULL != tslot, NULL); - } else if (NULL != tslot->team) { + if (tslot == NULL) { + return NULL; + } + } else if (tslot->team != NULL) { return tslot->team; } @@ -356,7 +358,6 @@ void team_destroy(struct team *pteam) struct team_slot *tslot; fc_assert_ret(team_slots_initialised()); - fc_assert_ret(NULL != pteam); fc_assert(0 == player_list_size(pteam->plrlist)); tslot = pteam->slot; @@ -460,22 +461,22 @@ const struct player_list *team_members(const struct team *pteam) } /************************************************************************//** - Set a player to a team. Removes the previous team affiliation if + Set a player to a team. Removes the previous team affiliation if necessary. ****************************************************************************/ -void team_add_player(struct player *pplayer, struct team *pteam) +bool team_add_player(struct player *pplayer, struct team *pteam) { - fc_assert_ret(pplayer != NULL); + fc_assert_ret_val(pplayer != NULL, FALSE); if (pteam == NULL) { pteam = team_new(NULL); + } else if (pteam == pplayer->team) { + /* It is the team of the player. */ + return TRUE; } - fc_assert_ret(pteam != NULL); - - if (pteam == pplayer->team) { - /* It is the team of the player. */ - return; + if (pteam == NULL) { + return FALSE; } log_debug("Adding player %d/%s to team %s.", player_number(pplayer), @@ -487,20 +488,22 @@ void team_add_player(struct player *pplayer, struct team *pteam) /* Put the player on the new team. */ pplayer->team = pteam; player_list_append(pteam->plrlist, pplayer); + + return TRUE; } /************************************************************************//** - Remove the player from the team. This should only be called when deleting + Remove the player from the team. This should only be called when deleting a player; since every player must always be on a team. - Note in some very rare cases a player may not be on a team. It's safe + Note in some very rare cases a player may not be on a team. It's safe to call this function anyway. ****************************************************************************/ void team_remove_player(struct player *pplayer) { struct team *pteam; - if (pplayer->team) { + if (pplayer->team != NULL) { pteam = pplayer->team; log_debug("Removing player %d/%s from team %s (%d)", @@ -512,5 +515,6 @@ void team_remove_player(struct player *pplayer) team_destroy(pteam); } } + pplayer->team = NULL; } diff --git a/common/team.h b/common/team.h index 2aca20f416..e5f3d3de67 100644 --- a/common/team.h +++ b/common/team.h @@ -1,4 +1,4 @@ -/********************************************************************** +/*********************************************************************** Freeciv - Copyright (C) 2005 - The Freeciv Project This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,10 +18,10 @@ extern "C" { #endif /* __cplusplus */ +/* common */ #include "fc_types.h" -#include "tech.h" - +/* Affects network protocol and savegames */ #define MAX_NUM_TEAM_SLOTS MAX_NUM_PLAYER_SLOTS /* Opaque types. */ @@ -50,7 +50,8 @@ void team_slot_set_defined_name(struct team_slot *tslot, const char *team_name); /* Team accessor functions. */ struct team *team_new(struct team_slot *tslot); -void team_destroy(struct team *pteam); +void team_destroy(struct team *pteam) + fc__attribute((nonnull(1))); int team_count(void); int team_index(const struct team *pteam); int team_number(const struct team *pteam); @@ -62,23 +63,25 @@ int team_pretty_name(const struct team *pteam, char *buf, size_t buf_len); const struct player_list *team_members(const struct team *pteam); /* Ancillary routines */ -void team_add_player(struct player *pplayer, struct team *pteam); +bool team_add_player(struct player *pplayer, struct team *pteam); void team_remove_player(struct player *pplayer); -/* iterate over all team slots */ +/* Iterate over all team slots */ #define team_slots_iterate(_tslot) \ if (team_slots_initialised()) { \ struct team_slot *_tslot = team_slot_first(); \ for (; NULL != _tslot; _tslot = team_slot_next(_tslot)) { + #define team_slots_iterate_end \ } \ } -/* iterate over all teams, which are used at the moment */ +/* Iterate over all teams, which are used at the moment */ #define teams_iterate(_pteam) \ team_slots_iterate(_tslot) { \ struct team *_pteam = team_slot_get_team(_tslot); \ if (_pteam != NULL) { + #define teams_iterate_end \ } \ } team_slots_iterate_end; diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c index d20f20e3f8..14e7510cd4 100644 --- a/server/savegame/savegame2.c +++ b/server/savegame/savegame2.c @@ -2555,6 +2555,7 @@ static void sg_load_players_basic(struct loaddata *loading) && (tslot = team_slot_by_number(team)), "Invalid team definition for player %s (nb %d).", player_name(pplayer), player_number(pplayer)); + /* Should never fail when slot given is not NULL */ team_add_player(pplayer, team_new(tslot)); } players_iterate_end; diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c index 51d9bdf55c..7fc8110911 100644 --- a/server/savegame/savegame3.c +++ b/server/savegame/savegame3.c @@ -3593,6 +3593,7 @@ static void sg_load_players_basic(struct loaddata *loading) && (tslot = team_slot_by_number(team)), "Invalid team definition for player %s (nb %d).", player_name(pplayer), player_number(pplayer)); + /* Should never fail when slot given is not NULL */ team_add_player(pplayer, team_new(tslot)); } players_iterate_end; diff --git a/server/stdinhand.c b/server/stdinhand.c index 131c849d89..fc1bb62324 100644 --- a/server/stdinhand.c +++ b/server/stdinhand.c @@ -2432,10 +2432,11 @@ static bool team_command(struct connection *caller, char *str, bool check) tslot = team_slot_by_number(teamno); } } + if (NULL == tslot) { cmd_reply(CMD_TEAM, caller, C_SYNTAX, _("No such team %s. Please give a " - "valid team name or number."), arg[1]); + "valid team name or number."), arg[1]); goto cleanup; } @@ -2444,19 +2445,23 @@ static bool team_command(struct connection *caller, char *str, bool check) cmd_reply(CMD_TEAM, caller, C_SYNTAX, _("Cannot team a barbarian.")); goto cleanup; } + if (!check) { + /* Should never fail when slot given is not NULL */ team_add_player(pplayer, team_new(tslot)); send_player_info_c(pplayer, NULL); cmd_reply(CMD_TEAM, caller, C_OK, _("Player %s set to team %s."), player_name(pplayer), team_slot_name_translation(tslot)); } + res = TRUE; cleanup: for (i = 0; i < ntokens; i++) { free(arg[i]); } + return res; } -- 2.40.1