Fix crash entering save game name

Commit e6875641c9 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 <https://github.com/dxx-rebirth/dxx-rebirth/issues/571>
Fixes: e6875641c9 ("Move Newmenu_allowed_chars into individual newmenu_item")
This commit is contained in:
Kp 2021-02-08 01:56:15 +00:00
parent 5465eda034
commit f19f66bdb7

View file

@ -855,10 +855,9 @@ static d_game_unique_state::save_slot state_get_savegame_filename(d_game_unique_
std::array<newmenu_item, NUM_SAVES + decorative_item_count> m; std::array<newmenu_item, NUM_SAVES + decorative_item_count> m;
auto &sc_bmp = userdata.sc_bmp; auto &sc_bmp = userdata.sc_bmp;
char id[4]; char id[4];
int valid;
nsaves=0; 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 /* Always subtract 1 for the fixed text leader. Conditionally
* subtract another 1 if the call is for saving, since interactive * subtract another 1 if the call is for saving, since interactive
* saves should not access the last slot. The last slot is reserved * 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)) range_for (const unsigned i, xrange(max_slots_shown))
{ {
state_format_savegame_filename(filename[i], i); 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]; auto &mi = m[i + decorative_item_count];
if (const auto fp = PHYSFSX_openReadBuffered(filename[i].data())) 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); PHYSFS_read(fp, desc[i].data(), desc[i].size(), 1);
desc[i].back() = 0; desc[i].back() = 0;
if (!dsc) if (!dsc)
mi.type = nm_type::menu; item_type = nm_type::menu;
// Read thumbnail // Read thumbnail
sc_bmp[i] = gr_create_bitmap(THUMBNAIL_W,THUMBNAIL_H ); sc_bmp[i] = gr_create_bitmap(THUMBNAIL_W,THUMBNAIL_H );
PHYSFS_read(fp, sc_bmp[i]->get_bitmap_data(), THUMBNAIL_W * THUMBNAIL_H, 1); 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; 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(); auto &im = mi.imenu();
im.allowed_chars = nullptr;
im.text_len = desc[i].size() - 1; im.text_len = desc[i].size() - 1;
im.group = 0;
} }
} }