diff --git a/SConstruct b/SConstruct
index 0e8d520f1..edd09b3d9 100644
--- a/SConstruct
+++ b/SConstruct
@@ -2576,36 +2576,6 @@ where the cast is useless.
'-Wsuggest-attribute=noreturn',
'-Wlogical-op',
'-Wold-style-cast',
- # Starting in gcc-7, Rebirth default options cause gcc to enable
- # -Wformat-truncation automatically. Unless proven otherwise by
- # data flow analysis, gcc pessimistically assumes that input
- # parameters might have their most space-consuming value (3
- # digits for a uint8_t, 5 for uint16_t, etc.). This causes
- # numerous warnings for places where Rebirth allocated a buffer
- # that is exactly big enough for the small numbers that are
- # actually used, but the data flow analysis is unable to prove
- # that larger numbers are not used.
- #
- # It would be nice to remove this option and eliminate the
- # warnings with fixes in the code, since this test completely
- # suppresses all -Wformat-truncation diagnostics, including any
- # that may be true bugs. However, gcc provides no documented
- # way to do this that does not generate extra runtime
- # instructions, which are unnecessary in at least some of the
- # cases where gcc warns.
- #
- # In testing, setting -Wformat-truncation=1 was insufficient to
- # silence a warning in similar/main/net_udp.cpp:
- #
- # similar/main/net_udp.cpp: In static member function 'static void {anonymous}::more_game_options_menu_items::net_udp_more_game_options()':
- # similar/main/net_udp.cpp:3528:6: error: ' Furthest Sites' directive output may be truncated writing 15 bytes into a region of size between 14 and 16 [-Werror=format-truncation=]
- # void more_game_options_menu_items::net_udp_more_game_options()
- # ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # similar/main/net_udp.cpp:3433:11: note: 'snprintf' output between 21 and 23 bytes into a destination of size 21
- # snprintf(SecludedSpawnText, sizeof(SecludedSpawnText), "Use %u Furthest Sites", Netgame.SecludedSpawns + 1);
- # ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- #
- '-Wno-format-truncation',
]
__preferred_win32_linker_options = [
'-Wl,--large-address-aware',
diff --git a/common/arch/sdl/joy.cpp b/common/arch/sdl/joy.cpp
index 4bcc9034c..bebe92e33 100644
--- a/common/arch/sdl/joy.cpp
+++ b/common/arch/sdl/joy.cpp
@@ -24,6 +24,7 @@
#include "compiler-range_for.h"
#if DXX_MAX_JOYSTICKS
+#include "compiler-cf_assert.h"
#include "compiler-integer_sequence.h"
#include "d_enumerate.h"
#include "partial_range.h"
@@ -294,7 +295,8 @@ void joy_init()
const auto n = check_warn_joy_support_limit(SDL_NumJoysticks(), "joystick", DXX_MAX_JOYSTICKS);
unsigned joystick_n_buttons = 0, joystick_n_axes = 0;
- for (int i = 0; i < n; i++) {
+ for (unsigned i = 0; i < n; i++)
+ {
auto &joystick = SDL_Joysticks[num_joysticks];
const auto handle = SDL_JoystickOpen(i);
joystick.handle().reset(handle);
@@ -311,6 +313,7 @@ void joy_init()
joyaxis_text.resize(joyaxis_text.size() + n_axes);
range_for (auto &&e, enumerate(partial_range(joystick.axis_map(), n_axes), 1))
{
+ cf_assert(e.idx <= DXX_MAX_AXES_PER_JOYSTICK);
auto &text = joyaxis_text[joystick_n_axes];
e.value = joystick_n_axes++;
snprintf(&text[0], sizeof(text), "J%d A%u", i + 1, e.idx);
@@ -325,6 +328,7 @@ void joy_init()
#if DXX_MAX_BUTTONS_PER_JOYSTICK
range_for (auto &&e, enumerate(partial_range(joystick.button_map(), n_buttons), 1))
{
+ cf_assert(e.idx <= DXX_MAX_BUTTONS_PER_JOYSTICK);
auto &text = joybutton_text[joystick_n_buttons];
e.value = joystick_n_buttons++;
snprintf(&text[0], sizeof(text), "J%d B%d", i + 1, e.idx);
@@ -334,6 +338,7 @@ void joy_init()
range_for (auto &&e, enumerate(partial_range(joystick.hat_map(), n_hats), 1))
{
e.value = joystick_n_buttons;
+ cf_assert(e.idx <= DXX_MAX_HATS_PER_JOYSTICK);
//a hat counts as four buttons
snprintf(&joybutton_text[joystick_n_buttons++][0], sizeof(joybutton_text[0]), "J%d H%d%c", i + 1, e.idx, 0202);
snprintf(&joybutton_text[joystick_n_buttons++][0], sizeof(joybutton_text[0]), "J%d H%d%c", i + 1, e.idx, 0177);
diff --git a/common/editor/autosave.cpp b/common/editor/autosave.cpp
index 0d286e8ce..d31719365 100644
--- a/common/editor/autosave.cpp
+++ b/common/editor/autosave.cpp
@@ -39,6 +39,8 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#include "ui.h"
#include "strutil.h"
+#include "compiler-cf_assert.h"
+
namespace dcx {
#define AUTOSAVE_PERIOD 5 // Number of minutes for timed autosave
@@ -66,7 +68,10 @@ void init_autosave(void) {
void close_autosave(void) {
char *ext;
- for (int i=0;i.
+ * It is copyright by its individual contributors, as recorded in the
+ * project's Git history. See COPYING.txt at the top level for license
+ * terms and a link to the Git history.
+ */
+#pragma once
+
+/* Define a utility macro `cf_assert` that, like `assert`, is meant to
+ * check invariants. Unlike `assert`, it has a small but configurable
+ * effect on NDEBUG builds.
+ *
+ * This macro is mainly used to try to hint to gcc that it is
+ * excessively cautious in determining whether a
+ * -Wformat-truncation warning is appropriate.
+ *
+ * Unless proved otherwise by control flow analysis, gcc will assume
+ * that a variable to be formatted could have any value that fits in the
+ * underlying type, and then gcc will warn if any of those values does
+ * not fit. In most cases, program logic constrains the value to a
+ * smaller range than the underlying type supports. Correct placement
+ * of this macro can inform the compiler that a variable's actual range
+ * is less than the full supported range of the underlying type. For
+ * example, a player counter should never exceed MAX_PLAYERS, but
+ * MAX_PLAYERS is far less than MAX_UCHAR.
+ *
+ * Unfortunately, in tested versions of gcc-8, the compiler's range
+ * propagation pass is hampered by strange rules in the flow control
+ * logic. Consider:
+
+ unsigned var = unconstrained_expression();
+ // var can now be anything in [0, UINT_MAX]
+ cf_assert(var <= 8);
+ // If execution gets here, `var <= 8` is true.
+ snprintf(..., var);
+
+ * Suppose cf_assert(X) is defined as `((X) || (assert(X),
+ * __builtin_unreachable()))`, so the above becomes:
+
+ unsigned var = unconstrained_expression();
+ if (var <= 8) {
+ }
+ else {
+ assert_fail(...);
+ __builtin_unreachable();
+ }
+ snprintf(..., var);
+
+ * In testing, gcc deleted __builtin_unreachable (probably because
+ * assert_fail is noreturn), then warned because, without the
+ * __builtin_unreachable, flow control decides the snprintf is reachable
+ * (even though assert_fail is noreturn) on the else path and would
+ * misbehave if reached. Remove the call to `assert` so that you have
+ * `else { __builtin_unreachable(); }` and gcc will retain the
+ * `__builtin_unreachable` and not warn.
+ *
+ * For an even more bizarre result:
+
+ if (var <= 8) {
+ snprintf(..., var);
+ } else {
+ assert(var <= 8); // always fails
+ __builtin_unreachable();
+ }
+
+ * This block warns that `var` is out of range. Comment out the
+ * `assert`, which cannot influence whether `snprintf` is reached, and
+ * the warning goes away.
+ *
+ * --
+ *
+ * Leave cf_assert set as an alias for (X || __builtin_unreachable())
+ * unless you know what you are doing and are prepared for the warnings
+ * that will arise.
+ */
+#include
+#if defined(DXX_CF_ASSERT_ASSERT)
+#define cf_assert assert
+#else
+#ifdef DXX_CF_ASSERT_TRAP
+#define cf_assert_fail __builtin_trap
+#else
+#define cf_assert_fail __builtin_unreachable
+#endif
+#define cf_assert(X) ((X) ? static_cast(0) : (cf_assert_fail()))
+#endif
diff --git a/common/ui/menubar.cpp b/common/ui/menubar.cpp
index 9c5415125..d7779a193 100644
--- a/common/ui/menubar.cpp
+++ b/common/ui/menubar.cpp
@@ -741,7 +741,7 @@ int menubar_init(grs_canvas &canvas, const char *const file)
{
int np;
char buf1[200];
- char buf2[200];
+ char buf2[204];
num_menus = state = 0;
@@ -786,7 +786,7 @@ int menubar_init(grs_canvas &canvas, const char *const file)
CommaParse( 2, buf1, buffer );
ul_xlate(buf1);
- item.Text.reset(d_strdup(buf1[0] == '-' ? buf1 : (snprintf(buf2, sizeof(buf2), " %s ", buf1), buf2)));
+ item.Text.reset(d_strdup(buf1[0] == '-' ? buf1 : (snprintf(buf2, sizeof(buf2), " %.197s ", buf1), buf2)));
item.InactiveText.reset(d_strdup(item.Text.get()));
diff --git a/d2x-rebirth/main/escort.cpp b/d2x-rebirth/main/escort.cpp
index 316091ddb..90783c16f 100644
--- a/d2x-rebirth/main/escort.cpp
+++ b/d2x-rebirth/main/escort.cpp
@@ -1741,7 +1741,7 @@ window_event_result escort_menu::event_handler(window *, const d_event &event, e
void do_escort_menu(void)
{
int next_goal;
- char goal_str[32];
+ char goal_str[12];
const char *goal_txt;
const char *tstr;
escort_menu *menu;
diff --git a/similar/editor/kmine.cpp b/similar/editor/kmine.cpp
index c5936c6f2..db82bff98 100644
--- a/similar/editor/kmine.cpp
+++ b/similar/editor/kmine.cpp
@@ -178,9 +178,9 @@ static int med_save_situation(char * filename)
{
auto SaveFile = PHYSFSX_openWriteBuffered(filename);
if (!SaveFile) {
- char ErrorMessage[200];
+ char ErrorMessage[512];
- snprintf(ErrorMessage, sizeof(ErrorMessage), "ERROR: Unable to open %s\n", filename);
+ snprintf(ErrorMessage, sizeof(ErrorMessage), "ERROR: Unable to open %.480s", filename);
ui_messagebox( -2, -2, 1, ErrorMessage, "Ok" );
return 1;
}
diff --git a/similar/main/bmread.cpp b/similar/main/bmread.cpp
index 0fbe7db28..e2e6b2aaa 100644
--- a/similar/main/bmread.cpp
+++ b/similar/main/bmread.cpp
@@ -267,7 +267,7 @@ static void ab_load(int skip, const char * filename, array tempname;
if (skip) {
Assert( bogus_bitmap_initialized != 0 );
@@ -293,11 +293,11 @@ static void ab_load(int skip, const char * filename, arrayavg_color = compute_average_pixel(bm[i].get());
- bmp[i] = piggy_register_bitmap(*bm[i].get(), tempname, 0);
+ bmp[i] = piggy_register_bitmap(*bm[i].get(), tempname.data(), 0);
}
}
diff --git a/similar/main/gameseq.cpp b/similar/main/gameseq.cpp
index dcb3cc380..828061029 100644
--- a/similar/main/gameseq.cpp
+++ b/similar/main/gameseq.cpp
@@ -893,16 +893,11 @@ void StartNewGame(int start_level)
static void DoEndLevelScoreGlitz()
{
int level_points, skill_points, energy_points, shield_points, hostage_points;
- int all_hostage_points;
- int endgame_points;
- char all_hostage_text[64];
- char endgame_text[64];
#define N_GLITZITEMS 9
- char m_str[N_GLITZITEMS][30];
+ char m_str[N_GLITZITEMS][32];
newmenu_item m[N_GLITZITEMS];
int i,c;
char title[128];
- int is_last_level;
#if defined(DXX_BUILD_DESCENT_I)
gr_palette_load( gr_palette );
#elif defined(DXX_BUILD_DESCENT_II)
@@ -947,26 +942,7 @@ static void DoEndLevelScoreGlitz()
hostage_points = 0;
}
- all_hostage_text[0] = 0;
- endgame_text[0] = 0;
-
auto &plr = get_local_player();
- if (!cheats.enabled && player_info.mission.hostages_on_board == plr.hostages_level)
- {
- all_hostage_points = player_info.mission.hostages_on_board * 1000 * (Difficulty_level+1);
- snprintf(all_hostage_text, sizeof(all_hostage_text), "%s%i\n", TXT_FULL_RESCUE_BONUS, all_hostage_points);
- } else
- all_hostage_points = 0;
-
- if (!cheats.enabled && !(Game_mode & GM_MULTI) && plr.lives && Current_level_num == Last_level)
- { //player has finished the game!
- endgame_points = plr.lives * 10000;
- snprintf(endgame_text, sizeof(endgame_text), "%s%i\n", TXT_SHIP_BONUS, endgame_points);
- is_last_level=1;
- } else
- endgame_points = is_last_level = 0;
-
- add_bonus_points_to_score(player_info, skill_points + energy_points + shield_points + hostage_points + all_hostage_points + endgame_points);
c = 0;
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_SHIELD_BONUS, shield_points); // Return at start to lower menu...
@@ -974,9 +950,35 @@ static void DoEndLevelScoreGlitz()
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_HOSTAGE_BONUS, hostage_points);
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_SKILL_BONUS, skill_points);
- snprintf(m_str[c++], sizeof(m_str[0]), "%s", all_hostage_text);
- if (!(Game_mode & GM_MULTI) && plr.lives && Current_level_num == Last_level)
- snprintf(m_str[c++], sizeof(m_str[0]), "%s", endgame_text);
+ const unsigned hostages_on_board = player_info.mission.hostages_on_board;
+ unsigned all_hostage_points = 0;
+ unsigned endgame_points = 0;
+ uint8_t is_last_level = 0;
+ auto &hostage_text = m_str[c++];
+ if (cheats.enabled)
+ snprintf(hostage_text, sizeof(hostage_text), "Hostages saved: \t%u", hostages_on_board);
+ else if (const auto hostages_lost = plr.hostages_level - hostages_on_board)
+ snprintf(hostage_text, sizeof(hostage_text), "Hostages lost: \t%u", hostages_lost);
+ else
+ {
+ all_hostage_points = hostages_on_board * 1000 * (Difficulty_level + 1);
+ snprintf(hostage_text, sizeof(hostage_text), "%s%i\n", TXT_FULL_RESCUE_BONUS, all_hostage_points);
+ }
+
+ auto &endgame_text = m_str[c++];
+ endgame_text[0] = 0;
+ if (cheats.enabled)
+ {
+ /* Nothing */
+ }
+ else if (!(Game_mode & GM_MULTI) && plr.lives && Current_level_num == Last_level)
+ { //player has finished the game!
+ endgame_points = plr.lives * 10000;
+ snprintf(endgame_text, sizeof(endgame_text), "%s%i\n", TXT_SHIP_BONUS, endgame_points);
+ is_last_level=1;
+ }
+
+ add_bonus_points_to_score(player_info, skill_points + energy_points + shield_points + hostage_points + all_hostage_points + endgame_points);
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i\n", TXT_TOTAL_BONUS, shield_points + energy_points + hostage_points + skill_points + all_hostage_points + endgame_points);
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_TOTAL_SCORE, player_info.mission.score);
diff --git a/similar/main/mission.cpp b/similar/main/mission.cpp
index f08fcb34d..0c7e3b8e3 100644
--- a/similar/main/mission.cpp
+++ b/similar/main/mission.cpp
@@ -216,10 +216,13 @@ static const char *load_mission_d1()
break;
case D1_OEM_MISSION_HOGSIZE:
case D1_OEM_10_MISSION_HOGSIZE:
+ {
N_secret_levels = 1;
- Last_level = 15;
- Last_secret_level = -1;
+ constexpr unsigned last_level = 15;
+ constexpr int last_secret_level = -1;
+ Last_level = last_level;
+ Last_secret_level = last_secret_level;
if (!allocate_levels())
{
@@ -228,14 +231,24 @@ static const char *load_mission_d1()
}
//build level names
- for (int i=0; i < Last_level - 1; i++)
- snprintf(&Level_names[i][0u], Level_names[i].size(), "level%02d.rdl", i+1);
- snprintf(&Level_names[Last_level - 1][0u], Level_names[Last_level - 1].size(), "saturn%02d.rdl", Last_level);
- for (int i=0; i < -Last_secret_level; i++)
- snprintf(&Secret_level_names[i][0u], Secret_level_names[i].size(), "levels%1d.rdl", i+1);
+ for (unsigned i = 0; i < last_level - 1; ++i)
+ {
+ auto &ln = Level_names[i];
+ snprintf(&ln[0u], ln.size(), "level%02u.rdl", i + 1);
+ }
+ {
+ auto &ln = Level_names[last_level - 1];
+ snprintf(&ln[0u], ln.size(), "saturn%02d.rdl", last_level);
+ }
+ for (int i = 0; i < -last_secret_level; ++i)
+ {
+ auto &sn = Secret_level_names[i];
+ snprintf(&sn[0u], sn.size(), "levels%1d.rdl", i + 1);
+ }
Secret_level_table[0] = 10;
Briefing_text_filename = "briefsat.txb";
Ending_text_filename = BIMD1_ENDING_FILE_OEM;
+ }
break;
default:
Int3(); // fall through
@@ -243,10 +256,13 @@ static const char *load_mission_d1()
case D1_MISSION_HOGSIZE2:
case D1_10_MISSION_HOGSIZE:
case D1_MAC_MISSION_HOGSIZE:
+ {
N_secret_levels = 3;
- Last_level = BIMD1_LAST_LEVEL;
- Last_secret_level = BIMD1_LAST_SECRET_LEVEL;
+ constexpr unsigned last_level = BIMD1_LAST_LEVEL;
+ constexpr int last_secret_level = BIMD1_LAST_SECRET_LEVEL;
+ Last_level = last_level;
+ Last_secret_level = last_secret_level;
if (!allocate_levels())
{
@@ -255,16 +271,23 @@ static const char *load_mission_d1()
}
//build level names
- for (int i=0;i m;
- array, entries> ljtext;
+ array, entries> ljtext;
};
manual_join_user_inputs manual_join::s_last_inputs;
@@ -1206,7 +1207,8 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
// Copy the active games data into the menu options
for (int i = 0; i < UDP_NETGAMES_PPAGE; i++)
{
- int game_status = Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_status;
+ const auto &augi = Active_udp_games[(i + (NLPage * UDP_NETGAMES_PPAGE))];
+ int game_status = augi.game_status;
int j,x, k,nplayers = 0;
char levelname[8],MissName[25],GameName[25],thold[2];
thold[1]=0;
@@ -1224,9 +1226,9 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
const auto &&fspacx = FSPACX();
for (x=0,k=0,j=0;j<15;j++)
{
- if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].mission_title[j]=='\t')
+ if (augi.mission_title[j]=='\t')
continue;
- thold[0]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].mission_title[j];
+ thold[0] = augi.mission_title[j];
int tx;
gr_get_string_size(*grd_curcanv->cv_font, thold, &tx, nullptr, nullptr);
@@ -1237,15 +1239,15 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
break;
}
- MissName[k++]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].mission_title[j];
+ MissName[k++] = augi.mission_title[j];
}
MissName[k]=0;
for (x=0,k=0,j=0;j<15;j++)
{
- if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_name[j]=='\t')
+ if (augi.game_name[j]=='\t')
continue;
- thold[0]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_name[j];
+ thold[0]=augi.game_name[j];
int tx;
gr_get_string_size(*grd_curcanv->cv_font, thold, &tx, nullptr, nullptr);
@@ -1255,25 +1257,32 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
k+=3;
break;
}
- GameName[k++]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_name[j];
+ GameName[k++]=augi.game_name[j];
}
GameName[k]=0;
- nplayers = Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].numconnected;
+ nplayers = augi.numconnected;
- if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].levelnum < 0)
- snprintf(levelname, sizeof(levelname), "S%d", -Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].levelnum);
+ const int levelnum = augi.levelnum;
+ if (levelnum < 0)
+ {
+ cf_assert(-levelnum < MAX_SECRET_LEVELS_PER_MISSION);
+ snprintf(levelname, sizeof(levelname), "S%d", -levelnum);
+ }
else
- snprintf(levelname, sizeof(levelname), "%d", Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].levelnum);
+ {
+ cf_assert(levelnum < MAX_LEVELS_PER_MISSION);
+ snprintf(levelname, sizeof(levelname), "%d", levelnum);
+ }
const char *status;
if (game_status == NETSTAT_STARTING)
status = "FORMING ";
else if (game_status == NETSTAT_PLAYING)
{
- if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].RefusePlayers)
+ if (augi.RefusePlayers)
status = "RESTRICT";
- else if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_flag.closed)
+ else if (augi.game_flag.closed)
status = "CLOSED ";
else
status = "OPEN ";
@@ -1281,9 +1290,9 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
else
status = "BETWEEN ";
- unsigned gamemode = Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].gamemode;
+ unsigned gamemode = augi.gamemode;
auto &p = dj->ljtext[i];
- snprintf(&p[0], p.size(), "%d.\t%s \t%s \t %d/%d \t%s \t %s \t%s", (i + (NLPage * UDP_NETGAMES_PPAGE)) + 1, GameName, (gamemode < sizeof(GMNamesShrt) / sizeof(GMNamesShrt[0])) ? GMNamesShrt[gamemode] : "INVALID", nplayers, Active_udp_games[(i + (NLPage * UDP_NETGAMES_PPAGE))].max_numplayers, MissName, levelname, status);
+ snprintf(&p[0], p.size(), "%d.\t%.24s \t%.7s \t%3u/%u \t%.24s \t %s \t%s", (i + (NLPage * UDP_NETGAMES_PPAGE)) + 1, GameName, (gamemode < sizeof(GMNamesShrt) / sizeof(GMNamesShrt[0])) ? GMNamesShrt[gamemode] : "INVALID", nplayers, augi.max_numplayers, MissName, levelname, status);
}
return 0;
}
@@ -3464,7 +3473,9 @@ public:
}
void update_secluded_spawn_string()
{
- snprintf(SecludedSpawnText, sizeof(SecludedSpawnText), "Use %u Furthest Sites", Netgame.SecludedSpawns + 1);
+ const unsigned SecludedSpawns = Netgame.SecludedSpawns;
+ cf_assert(SecludedSpawns < MAX_PLAYERS);
+ snprintf(SecludedSpawnText, sizeof(SecludedSpawnText), "Use %u Furthest Sites", SecludedSpawns + 1);
}
void update_kill_goal_string()
{
@@ -3712,7 +3723,9 @@ struct param_opt
}
void update_max_players_string()
{
- snprintf(srmaxnet, sizeof(srmaxnet), "Maximum players: %u", Netgame.max_numplayers);
+ const unsigned max_numplayers = Netgame.max_numplayers;
+ cf_assert(max_numplayers < MAX_PLAYERS);
+ snprintf(srmaxnet, sizeof(srmaxnet), "Maximum players: %u", max_numplayers);
}
};
diff --git a/similar/main/newdemo.cpp b/similar/main/newdemo.cpp
index f5e305bd0..583c6411a 100644
--- a/similar/main/newdemo.cpp
+++ b/similar/main/newdemo.cpp
@@ -3876,7 +3876,7 @@ static void newdemo_write_end()
nd_write_byte(ND_EVENT_EOF);
}
-static bool guess_demo_name(ntstring &filename)
+static bool guess_demo_name(ntstring &filename)
{
filename[0] = 0;
const auto &n = CGameArg.SysRecordDemoNameTemplate;
@@ -3964,7 +3964,7 @@ void newdemo_stop_recording()
{
int exit;
static sbyte tmpcnt = 0;
- ntstring filename;
+ ntstring filename;
exit = 0;
diff --git a/similar/main/piggy.cpp b/similar/main/piggy.cpp
index 00e0dbf97..762957305 100644
--- a/similar/main/piggy.cpp
+++ b/similar/main/piggy.cpp
@@ -620,6 +620,7 @@ int properties_init()
return retval;
}
#elif defined(DXX_BUILD_DESCENT_II)
+
//initialize a pigfile, reading headers
//returns the size of all the bitmap data
void piggy_init_pigfile(const char *filename)
@@ -819,6 +820,7 @@ void piggy_new_pigfile(char *pigname)
unsigned nframes;
const std::size_t len = p - AllBitmaps[i].name.data();
+ cf_assert(len < AllBitmaps[i].name.size());
memcpy(basename, AllBitmaps[i].name.data(), len);
basename[len] = 0;