Test whether change_filename_extension succeeded before using its output

This commit is contained in:
Kp 2022-10-09 23:15:20 +00:00
parent b0ebe3b82c
commit 0ebcc64ac5
8 changed files with 35 additions and 17 deletions

View file

@ -61,7 +61,8 @@ struct splitpath_t
void removeext(const char *filename, std::array<char, 20> &out); void removeext(const char *filename, std::array<char, 20> &out);
//give a filename a new extension, doesn't work with paths with no extension already there //give a filename a new extension, doesn't work with paths with no extension already there
void change_filename_extension(std::span<char> dest, const char *src, std::span<const char, 4> ext); [[nodiscard]]
bool change_filename_extension(std::span<char> dest, const char *src, std::span<const char, 4> ext);
/* Given an MS-DOS path, return pointers to the start of the basename and the /* Given an MS-DOS path, return pointers to the start of the basename and the
* start of the extension. * start of the extension.

View file

@ -136,16 +136,17 @@ void removeext(const char *const filename, std::array<char, 20> &out)
} }
//give a filename a new extension, won't append if strlen(dest) > 8 chars. //give a filename a new extension, won't append if strlen(dest) > 8 chars.
void change_filename_extension(const std::span<char> dest, const char *const src, const std::span<const char, 4> ext) bool change_filename_extension(const std::span<char> dest, const char *const src, const std::span<const char, 4> ext)
{ {
const char *const p = strrchr(src, '.'); const char *const p = strrchr(src, '.');
const std::size_t src_dist_to_last_dot = p ? std::distance(src, p) : strlen(src); const std::size_t src_dist_to_last_dot = p ? std::distance(src, p) : strlen(src);
if (src_dist_to_last_dot + 1 + ext.size() > dest.size()) if (src_dist_to_last_dot + 1 + ext.size() > dest.size())
{ {
dest.front() = 0; dest.front() = 0;
return; // a non-opened file is better than a bad memory access return false; // a non-opened file is better than a bad memory access
} }
std::snprintf(dest.data(), dest.size(), "%.*s.%s", static_cast<int>(src_dist_to_last_dot), src, ext.data()); std::snprintf(dest.data(), dest.size(), "%.*s.%s", static_cast<int>(src_dist_to_last_dot), src, ext.data());
return true;
} }
splitpath_t d_splitpath(const char *name) splitpath_t d_splitpath(const char *name)

View file

@ -518,7 +518,11 @@ static int init_subtitles(d_loaded_subtitle_state &SubtitleState, const std::spa
if (!ifile) { //no text version, try binary version if (!ifile) { //no text version, try binary version
std::array<char, FILENAME_LEN> filename2; std::array<char, FILENAME_LEN> filename2;
change_filename_extension(filename2, filename.data(), "txb"); if (!change_filename_extension(filename2, filename.data(), "txb"))
{
con_printf(CON_NORMAL, "Rebirth: skipping subtitles because cannot open \"%s\" (\"%s\")", filename.data(), PHYSFS_getErrorByCode(physfserr));
return 0;
}
auto &&[ifile2, physfserr2] = PHYSFSX_openReadBuffered(filename2.data()); auto &&[ifile2, physfserr2] = PHYSFSX_openReadBuffered(filename2.data());
if (!ifile2) if (!ifile2)
{ {

View file

@ -538,7 +538,11 @@ void load_robot_replacements(const d_fname &level_name)
auto &Robot_joints = LevelSharedRobotJointState.Robot_joints; auto &Robot_joints = LevelSharedRobotJointState.Robot_joints;
int t,j; int t,j;
std::array<char, FILENAME_LEN> ifile_name; std::array<char, FILENAME_LEN> ifile_name;
change_filename_extension(ifile_name, level_name, "HXM"); if (!change_filename_extension(ifile_name, level_name, "HXM"))
{
con_printf(CON_URGENT, "Failed to generate HXM name from level name \"%s\"", level_name.data());
return;
}
auto fp = PHYSFSX_openReadBuffered(ifile_name.data()).first; auto fp = PHYSFSX_openReadBuffered(ifile_name.data()).first;
if (!fp) //no robot replacement file if (!fp) //no robot replacement file

View file

@ -1845,12 +1845,18 @@ static int save_level_sub(
} }
// else // else
{ {
auto &level_file_extension =
#if defined(DXX_BUILD_DESCENT_II) #if defined(DXX_BUILD_DESCENT_II)
if (Gamesave_current_version > 3) (Gamesave_current_version > 3)
change_filename_extension(temp_filename, filename, D2X_LEVEL_FILE_EXTENSION); ? D2X_LEVEL_FILE_EXTENSION
else :
#endif #endif
change_filename_extension(temp_filename, filename, D1X_LEVEL_FILE_EXTENSION); D1X_LEVEL_FILE_EXTENSION;
if (!change_filename_extension(temp_filename, filename, level_file_extension))
{
con_printf(CON_URGENT, "Failed to generate filename for level data from \"%s\"", filename);
return 1;
}
} }
auto &&[SaveFile, physfserr] = PHYSFSX_openWriteBuffered(temp_filename.data()); auto &&[SaveFile, physfserr] = PHYSFSX_openWriteBuffered(temp_filename.data());

View file

@ -876,7 +876,8 @@ static window_event_result demo_menu_keycommand( listbox *lb,const d_event &even
// Get backup name // Get backup name
const auto ic = items[citem]; const auto ic = items[citem];
change_filename_extension(bakname, ic, DEMO_BACKUP_EXT); if (!change_filename_extension(bakname, ic, DEMO_BACKUP_EXT))
return window_event_result::handled;
const auto x = nm_messagebox(menu_title{nullptr}, 2, TXT_YES, TXT_NO, "Are you sure you want to\n" const auto x = nm_messagebox(menu_title{nullptr}, 2, TXT_YES, TXT_NO, "Are you sure you want to\n"
"swap the endianness of\n" "swap the endianness of\n"
"%s? If the file is\n" "%s? If the file is\n"

View file

@ -4360,11 +4360,9 @@ int newdemo_swap_endian(const char *filename)
infile.reset(); infile.reset();
outfile.reset(); outfile.reset();
if (complete) std::array<char, PATH_MAX> bakpath;
if (complete && change_filename_extension(bakpath, inpath, DEMO_BACKUP_EXT))
{ {
std::array<char, PATH_MAX> bakpath;
change_filename_extension(bakpath, inpath, DEMO_BACKUP_EXT);
PHYSFSX_rename(inpath, bakpath.data()); PHYSFSX_rename(inpath, bakpath.data());
PHYSFSX_rename(DEMO_FILENAME, inpath); PHYSFSX_rename(DEMO_FILENAME, inpath);
} }

View file

@ -1542,9 +1542,11 @@ static void piggy_write_pigfile(const std::span<const char, FILENAME_LEN> filena
data_offset = bitmap_data_start; data_offset = bitmap_data_start;
std::array<char, FILENAME_LEN> tname; std::array<char, FILENAME_LEN> tname;
change_filename_extension(tname, filename.data(), "lst"); if (!change_filename_extension(tname, filename.data(), "lst"))
return;
auto fp1 = PHYSFSX_openWriteBuffered(tname.data()).first; auto fp1 = PHYSFSX_openWriteBuffered(tname.data()).first;
change_filename_extension(tname, filename.data(), "all"); if (!change_filename_extension(tname, filename.data(), "all"))
return;
auto fp2 = PHYSFSX_openWriteBuffered(tname.data()).first; auto fp2 = PHYSFSX_openWriteBuffered(tname.data()).first;
for (i=1; i < Num_bitmap_files; i++ ) { for (i=1; i < Num_bitmap_files; i++ ) {
@ -1785,7 +1787,8 @@ void load_bitmap_replacements(const std::span<const char, FILENAME_LEN> level_na
free_bitmap_replacements(); free_bitmap_replacements();
std::array<char, FILENAME_LEN> ifile_name; std::array<char, FILENAME_LEN> ifile_name;
change_filename_extension(ifile_name, level_name.data(), "POG"); if (!change_filename_extension(ifile_name, level_name.data(), "POG"))
return;
if (auto ifile = PHYSFSX_openReadBuffered(ifile_name.data()).first) if (auto ifile = PHYSFSX_openReadBuffered(ifile_name.data()).first)
{ {
int id,version; int id,version;