From 0e4e1b728570c664907d903e97c69b897ff6bec5 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 19 May 2015 04:19:41 +0200 Subject: [PATCH] Fix crashes when loading savegame savegame/tables/fields.h was missing some fields with FFL_NOSPAWN and FFL_NOSPAWN handling in g_spawn.c was missing Because of that after loading a savegame some pointers were invalid and dereferencing them resulted in segfaults. --- src/g_spawn.c | 50 +++++++++++++++++++++++++++++++++++- src/header/local.h | 1 + src/savegame/savegame.c | 12 ++++++++- src/savegame/tables/fields.h | 32 +++++++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/g_spawn.c b/src/g_spawn.c index cc3b84f..bc169e5 100644 --- a/src/g_spawn.c +++ b/src/g_spawn.c @@ -306,6 +306,11 @@ void ED_CallSpawn (edict_t *ent) gitem_t *item; int i; + if (!ent) + { + return; + } + if (!ent->classname) { gi.dprintf ("ED_CallSpawn: NULL classname\n"); @@ -346,6 +351,11 @@ char *ED_NewString (const char *string) char *newb, *new_p; int i,l; + if (!string) + { + return NULL; + } + l = strlen(string) + 1; newb = gi.TagMalloc (l, TAG_LEVEL); @@ -384,9 +394,14 @@ void ED_ParseField (const char *key, const char *value, edict_t *ent) float v; vec3_t vec; + if (!ent || !value || !key) + { + return; + } + for (f=fields ; f->name ; f++) { - if (!Q_stricmp(f->name, key)) + if (!(f->flags & FFL_NOSPAWN) && !Q_stricmp(f->name, key)) { // found it if (f->flags & FFL_SPAWNTEMP) b = (byte *)&st; @@ -441,6 +456,11 @@ char *ED_ParseEdict (char *data, edict_t *ent) char keyname[256]; const char *com_token; + if (!ent || !data) + { + return NULL; + } + init = false; memset (&st, 0, sizeof(st)); @@ -530,6 +550,8 @@ void G_FindTeams (void) } } + // FIXME: DG: G_FixTeams(); like rogue? + gi.dprintf ("%i teams with %i entities\n", c, c2); } @@ -610,6 +632,32 @@ void SpawnEntities (const char *mapname, char *entities, const char *spawnpoint) continue; } } +#if 0 // FIXME: DG: coop stuff from rogue + else if (coop->value) + { + if (ent->spawnflags & SPAWNFLAG_NOT_COOP) + { + G_FreeEdict(ent); + inhibit++; + continue; + } + + /* stuff marked !easy & !med & !hard are coop only, all levels */ + if (!((ent->spawnflags & SPAWNFLAG_NOT_EASY) && + (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM) && + (ent->spawnflags & SPAWNFLAG_NOT_HARD))) + { + if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || + ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || + (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) + { + G_FreeEdict(ent); + inhibit++; + continue; + } + } + } +#endif // 0 else { if (((!coop->value) && (ent->spawnflags2 & SPAWNFLAG2_NOT_SINGLE)) || diff --git a/src/header/local.h b/src/header/local.h index 2c6d4d2..7063665 100644 --- a/src/header/local.h +++ b/src/header/local.h @@ -615,6 +615,7 @@ extern cvar_t *bettyammo; // and saving / loading games // #define FFL_SPAWNTEMP 1 +#define FFL_NOSPAWN 2 typedef enum { F_INT, diff --git a/src/savegame/savegame.c b/src/savegame/savegame.c index da63720..2a30e0f 100644 --- a/src/savegame/savegame.c +++ b/src/savegame/savegame.c @@ -54,7 +54,7 @@ * in tables/ are changed, otherwise * strange things may happen. */ -#define SAVEGAMEVER "YQ2-1" +#define SAVEGAMEVER "YQ2-2" /* * This macros are used to @@ -66,8 +66,14 @@ */ #if defined(__FreeBSD__) #define OS "FreeBSD" +#elif defined(__APPLE__) + #define OS "MacOS X" +#elif defined(__OpenBSD__) + #define OS "OpenBSD" #elif defined(__linux__) #define OS "Linux" +#elif defined(_WIN32) + #define OS "Windows" #else #define OS "Unknown" #endif @@ -76,6 +82,10 @@ #define ARCH "i386" #elif defined(__x86_64__) #define ARCH "amd64" +#elif defined(__sparc__) + #define ARCH "sparc64" +#elif defined(__ia64__) + #define ARCH "ia64" #else #define ARCH "unknown" #endif diff --git a/src/savegame/tables/fields.h b/src/savegame/tables/fields.h index b1c0297..bc2c30b 100644 --- a/src/savegame/tables/fields.h +++ b/src/savegame/tables/fields.h @@ -38,6 +38,38 @@ {"origin", FOFS(s.origin), F_VECTOR}, {"angles", FOFS(s.angles), F_VECTOR}, {"angle", FOFS(s.angles), F_ANGLEHACK}, +{"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN}, +{"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN}, +{"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN}, +{"oldenemy", FOFS(oldenemy), F_EDICT, FFL_NOSPAWN}, +{"activator", FOFS(activator), F_EDICT, FFL_NOSPAWN}, +{"groundentity", FOFS(groundentity), F_EDICT, FFL_NOSPAWN}, +{"teamchain", FOFS(teamchain), F_EDICT, FFL_NOSPAWN}, +{"teammaster", FOFS(teammaster), F_EDICT, FFL_NOSPAWN}, +{"owner", FOFS(owner), F_EDICT, FFL_NOSPAWN}, +{"mynoise", FOFS(mynoise), F_EDICT, FFL_NOSPAWN}, +{"mynoise2", FOFS(mynoise2), F_EDICT, FFL_NOSPAWN}, +{"target_ent", FOFS(target_ent), F_EDICT, FFL_NOSPAWN}, +{"chain", FOFS(chain), F_EDICT, FFL_NOSPAWN}, +{"prethink", FOFS(prethink), F_FUNCTION, FFL_NOSPAWN}, +{"think", FOFS(think), F_FUNCTION, FFL_NOSPAWN}, +{"blocked", FOFS(blocked), F_FUNCTION, FFL_NOSPAWN}, +{"touch", FOFS(touch), F_FUNCTION, FFL_NOSPAWN}, +{"use", FOFS(use), F_FUNCTION, FFL_NOSPAWN}, +{"pain", FOFS(pain), F_FUNCTION, FFL_NOSPAWN}, +{"die", FOFS(die), F_FUNCTION, FFL_NOSPAWN}, +{"stand", FOFS(monsterinfo.stand), F_FUNCTION, FFL_NOSPAWN}, +{"idle", FOFS(monsterinfo.idle), F_FUNCTION, FFL_NOSPAWN}, +{"search", FOFS(monsterinfo.search), F_FUNCTION, FFL_NOSPAWN}, +{"walk", FOFS(monsterinfo.walk), F_FUNCTION, FFL_NOSPAWN}, +{"run", FOFS(monsterinfo.run), F_FUNCTION, FFL_NOSPAWN}, +{"dodge", FOFS(monsterinfo.dodge), F_FUNCTION, FFL_NOSPAWN}, +{"attack", FOFS(monsterinfo.attack), F_FUNCTION, FFL_NOSPAWN}, +{"melee", FOFS(monsterinfo.melee), F_FUNCTION, FFL_NOSPAWN}, +{"sight", FOFS(monsterinfo.sight), F_FUNCTION, FFL_NOSPAWN}, +{"checkattack", FOFS(monsterinfo.checkattack), F_FUNCTION, FFL_NOSPAWN}, +{"currentmove", FOFS(monsterinfo.currentmove), F_MMOVE, FFL_NOSPAWN}, +{"endfunc", FOFS(moveinfo.endfunc), F_FUNCTION, FFL_NOSPAWN}, {"mangle", FOFS(mangle), F_VECTOR}, {"active", FOFS(active), F_INT}, {"spawnflags2", FOFS(spawnflags2), F_INT},