From c39a070f13c19c2cf30bb961426bea8c5140c9a5 Mon Sep 17 00:00:00 2001 From: haranp Date: Wed, 19 Sep 2007 23:28:26 +0000 Subject: Fix for memory corruption when reading savefiles. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2152 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/externs.h | 20 +++++++++++++------- crawl-ref/source/files.cc | 31 ++++++++++++++++-------------- crawl-ref/source/files.h | 2 +- crawl-ref/source/newgame.cc | 15 ++++++++------- crawl-ref/source/player.cc | 46 ++++++++++++++++++++++----------------------- crawl-ref/source/state.cc | 3 ++- 6 files changed, 63 insertions(+), 54 deletions(-) diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 7dbdcbe9eb..e6dee9a54d 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -681,13 +681,6 @@ public: void init(); - bool is_valid() const; - std::string short_desc() const; - - // For sorting - bool operator < (const player &p) const; - -public: // Low-level move the player to (x, y). Use these functions instead of // changing x_pos and y_pos directly. void moveto(int x, int y); @@ -814,6 +807,19 @@ public: extern player you; +struct player_save_info +{ + std::string name; + unsigned long experience; + int experience_level; + bool wizard; + species_type species; + std::string class_name; + player_save_info operator=(const player& rhs); + bool operator<(const player_save_info& rhs) const; + std::string short_desc() const; +}; + class monster_spells : public FixedVector { public: diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 7e2cf37bed..20a0a93579 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -33,6 +33,7 @@ #include #include +#include #ifdef DOS #include @@ -175,12 +176,10 @@ bool is_packed_save(const std::string &name) } #endif -// Returns a full player struct read from the save. -player read_character_info(const std::string &savefile) +// Return the save_info from the save. +player_save_info read_character_info(const std::string &savefile) { - player fromfile; - player backup; - + player_save_info fromfile; FILE *charf = fopen(savefile.c_str(), "rb"); if (!charf) return fromfile; @@ -188,13 +187,16 @@ player read_character_info(const std::string &savefile) char majorVersion = 0; char minorVersion = 0; - backup.copy_from(you); if (determine_version(charf, majorVersion, minorVersion) && majorVersion == SAVE_MAJOR_VERSION) { + // backup before we clobber "you" + const player backup(you); + restore_tagged_file(charf, TAGTYPE_PLAYER_NAME, minorVersion); - fromfile.copy_from(you); - you .copy_from(backup); + + fromfile = you; + you.copy_from(backup); } fclose(charf); @@ -450,9 +452,10 @@ std::string get_savedir_path(const std::string &shortpath) * Returns a list of the names of characters that are already saved for the * current user. */ -std::vector find_saved_characters() + +std::vector find_saved_characters() { - std::vector chars; + std::vector chars; #ifndef DISABLE_SAVEGAME_LISTS std::string searchpath = Options.save_dir; @@ -460,7 +463,7 @@ std::vector find_saved_characters() searchpath = "."; std::vector allfiles = get_dir_files(searchpath); - for (int i = 0, size = allfiles.size(); i < size; ++i) + for (unsigned int i = 0; i < allfiles.size(); ++i) { std::string filename = allfiles[i]; #ifdef LOAD_UNPACKAGE_CMD @@ -490,8 +493,8 @@ std::vector find_saved_characters() #endif if (is_save_file_name(filename)) { - player p = read_character_info(get_savedir_path(filename)); - if (p.is_valid()) + player_save_info p=read_character_info(get_savedir_path(filename)); + if (!p.name.empty()) chars.push_back(p); } @@ -501,7 +504,7 @@ std::vector find_saved_characters() #endif } - std::sort(chars.begin(), chars.end()); + std::sort(chars.rbegin(), chars.rend()); #endif // !DISABLE_SAVEGAME_LISTS return (chars); } diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index 9e996613dc..8a9cf6a6c8 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -42,7 +42,7 @@ bool check_dir(const std::string &what, std::string &dir, bool silent = false); bool travel_load_map( branch_type branch, int absdepth ); -std::vector find_saved_characters(); +std::vector find_saved_characters(); std::string get_savedir(); std::string get_savedir_filename(const std::string &pre, diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 1ec22646ee..fbd065ab20 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -2114,7 +2114,7 @@ static void openingScreen(void) } static void show_name_prompt(int where, bool blankOK, - const std::vector &existing_chars, + const std::vector &existing_chars, slider_menu &menu) { gotoxy(1, where); @@ -2204,7 +2204,7 @@ static int newname_keyfilter(int &ch) static bool read_player_name( char *name, int len, - const std::vector &existing, + const std::vector &existing, slider_menu &menu) { const int name_x = wherex(), name_y = wherey(); @@ -2236,8 +2236,9 @@ static bool read_player_name( const MenuEntry *sel = menu.selected_entry(); if (sel) { - const player &p = *static_cast( sel->data ); - strncpy(name, p.your_name, kNameLen); + const player_save_info &p = + *static_cast( sel->data ); + strncpy(name, p.name.c_str(), kNameLen); name[kNameLen - 1] = 0; return (true); } @@ -2252,7 +2253,7 @@ static void enter_player_name(bool blankOK) int prompt_start = wherey(); bool ask_name = true; char *name = you.your_name; - std::vector existing_chars; + std::vector existing_chars; slider_menu char_menu; if (you.your_name[0] != 0) @@ -2261,7 +2262,7 @@ static void enter_player_name(bool blankOK) if (blankOK && (ask_name || !is_good_name(you.your_name, false, false))) { existing_chars = find_saved_characters(); - if (existing_chars.size() == 0) + if (existing_chars.empty()) { gotoxy(1,12); formatted_string::parse_string( @@ -2273,7 +2274,7 @@ static void enter_player_name(bool blankOK) MenuEntry *title = new MenuEntry("Or choose an existing character:"); title->colour = LIGHTCYAN; char_menu.set_title( title ); - for (int i = 0, size = existing_chars.size(); i < size; ++i) + for (unsigned int i = 0; i < existing_chars.size(); ++i) { std::string desc = " " + existing_chars[i].short_desc(); if (static_cast(desc.length()) >= get_number_of_cols()) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 77b4fbe3e1..a7888acab3 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -30,6 +30,8 @@ #include #include +#include + #include "externs.h" #include "branch.h" @@ -5124,45 +5126,41 @@ void player::init() } } -player::~player() +player_save_info player_save_info::operator=(const player& rhs) { - delete kills; + name = rhs.your_name; + experience = rhs.experience; + experience_level = rhs.experience_level; + wizard = rhs.wizard; + species = rhs.species; + class_name = rhs.class_name; + return *this; } -bool player::is_valid() const +bool player_save_info::operator<(const player_save_info& rhs) const { - // Check if there's a name. - return (your_name[0] != 0); + return experience < rhs.experience || + (experience == rhs.experience && name < rhs.name); } -std::string player::short_desc() const +std::string player_save_info::short_desc() const { - std::string desc; - desc += your_name; - desc += ", a level "; - - char st_prn[20]; - itoa(experience_level, st_prn, 10); - desc += st_prn; - - desc += " "; - desc += species_name(species, experience_level); - desc += " "; - desc += class_name; + std::ostringstream desc; + desc << name << ", a level " << experience_level << ' ' + << species_name(species, experience_level) << ' ' + << class_name; #ifdef WIZARD if (wizard) - desc += " (WIZ)"; + desc << " (WIZ)"; #endif - return (desc); + return desc.str(); } -bool player::operator < (const player &p) const +player::~player() { - return (experience > p.experience - || (experience == p.experience && - stricmp(your_name, p.your_name) < 0)); + delete kills; } coord_def player::pos() const diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index 41c4837dff..f7bd86bc7d 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -16,8 +16,9 @@ #include "delay.h" #include "direct.h" #include "macro.h" -#include "mon-util.h" #include "menu.h" // For print_formatted_paragraph() +#include "message.h" +#include "mon-util.h" #include "player.h" #include "state.h" #include "tutorial.h" -- cgit v1.2.3-54-g00ecf