summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2007-09-19 23:28:26 +0000
committerharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2007-09-19 23:28:26 +0000
commitc39a070f13c19c2cf30bb961426bea8c5140c9a5 (patch)
tree636060955c9a3d7cc61aebc0b181c541d9e6024b
parent7b52c20fd2613f4597a5b429c604369d393367ec (diff)
downloadcrawl-ref-c39a070f13c19c2cf30bb961426bea8c5140c9a5.tar.gz
crawl-ref-c39a070f13c19c2cf30bb961426bea8c5140c9a5.zip
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
-rw-r--r--crawl-ref/source/externs.h20
-rw-r--r--crawl-ref/source/files.cc31
-rw-r--r--crawl-ref/source/files.h2
-rw-r--r--crawl-ref/source/newgame.cc15
-rw-r--r--crawl-ref/source/player.cc46
-rw-r--r--crawl-ref/source/state.cc3
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<spell_type, NUM_MONSTER_SPELL_SLOTS>
{
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 <ctype.h>
#include <algorithm>
+#include <functional>
#ifdef DOS
#include <conio.h>
@@ -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<player> find_saved_characters()
+
+std::vector<player_save_info> find_saved_characters()
{
- std::vector<player> chars;
+ std::vector<player_save_info> chars;
#ifndef DISABLE_SAVEGAME_LISTS
std::string searchpath = Options.save_dir;
@@ -460,7 +463,7 @@ std::vector<player> find_saved_characters()
searchpath = ".";
std::vector<std::string> 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<player> 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<player> 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<player> find_saved_characters();
+std::vector<player_save_info> 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<player> &existing_chars,
+ const std::vector<player_save_info> &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<player> &existing,
+ const std::vector<player_save_info> &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<player*>( sel->data );
- strncpy(name, p.your_name, kNameLen);
+ const player_save_info &p =
+ *static_cast<player_save_info*>( 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<player> existing_chars;
+ std::vector<player_save_info> 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<int>(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 <math.h>
#include <ctype.h>
+#include <sstream>
+
#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"