From f19f66bdb7cedde89c3cdff14f96cc924e6146cd Mon Sep 17 00:00:00 2001 From: Kp Date: Mon, 8 Feb 2021 01:56:15 +0000 Subject: [PATCH] Fix crash entering save game name Commit e6875641c9b8 moved allowed_chars from global scope into individual newmenu_item entries. However, it did not enforce that this field be initialized, and some callers failed to do so. The save game menu was such a caller, and crashed when using an uninitialized value as the allowed_chars pointer. There is no character restriction here, so explicitly set the pointer to nullptr. Reported-by: kitelessd Fixes: e6875641c9b838a2f931c091d7c8927accd764f1 ("Move Newmenu_allowed_chars into individual newmenu_item") --- similar/main/state.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/similar/main/state.cpp b/similar/main/state.cpp index c38b6ae96..19754dc35 100644 --- a/similar/main/state.cpp +++ b/similar/main/state.cpp @@ -855,10 +855,9 @@ static d_game_unique_state::save_slot state_get_savegame_filename(d_game_unique_ std::array m; auto &sc_bmp = userdata.sc_bmp; char id[4]; - int valid; nsaves=0; - nm_set_item_text(m[0], "\n\n\n"); + nm_set_item_text(m[0], "\n\n\n\n"); /* Always subtract 1 for the fixed text leader. Conditionally * subtract another 1 if the call is for saving, since interactive * saves should not access the last slot. The last slot is reserved @@ -868,7 +867,17 @@ static d_game_unique_state::save_slot state_get_savegame_filename(d_game_unique_ range_for (const unsigned i, xrange(max_slots_shown)) { state_format_savegame_filename(filename[i], i); - valid = 0; + nm_type item_type = dsc + /* If saving, use input_menu so that the user can pick an + * element and convert it into a text entry field to receive + * the save game title. + */ + ? nm_type::input_menu + /* If restoring, use text. Valid save games will switch the + * type. Invalid save slots will remain set as text. + */ + : nm_type::text; + uint8_t valid = 0; auto &mi = m[i + decorative_item_count]; if (const auto fp = PHYSFSX_openReadBuffered(filename[i].data())) { @@ -887,7 +896,7 @@ static d_game_unique_state::save_slot state_get_savegame_filename(d_game_unique_ PHYSFS_read(fp, desc[i].data(), desc[i].size(), 1); desc[i].back() = 0; if (!dsc) - mi.type = nm_type::menu; + item_type = nm_type::menu; // Read thumbnail sc_bmp[i] = gr_create_bitmap(THUMBNAIL_W,THUMBNAIL_H ); PHYSFS_read(fp, sc_bmp[i]->get_bitmap_data(), THUMBNAIL_W * THUMBNAIL_H, 1); @@ -902,18 +911,21 @@ static d_game_unique_state::save_slot state_get_savegame_filename(d_game_unique_ valid = 1; } } - } - mi.text = desc[i].data(); - if (!valid) { - strcpy(desc[i].data(), TXT_EMPTY); - if (!dsc) - mi.type = nm_type::text; } - if (dsc) + mi.text = desc[i].data(); + if (!valid) + /* Defer setting a default value to here. This allows the + * value to be written only if a better one was not + * retrieved from a save game file. + */ + strcpy(desc[i].data(), TXT_EMPTY); + mi.type = item_type; + if (item_type == nm_type::input_menu) { - mi.type = nm_type::input_menu; auto &im = mi.imenu(); + im.allowed_chars = nullptr; im.text_len = desc[i].size() - 1; + im.group = 0; } }