View Issue Details

IDProjectCategoryView StatusLast Update
0001320FSSCPgameplaypublic2010-12-07 17:19
Reportercmb Assigned To 
PrioritylowSeveritycrashReproducibilityalways
Status closedResolutionno change required 
Platformi686 (Athlon XP)OSDebian GNU/LinuxOS Versionunstable
Summary0001320: Unstable: Retail pilot file crash: too many subsys_aggregate_current_hits
DescriptionBoth debug and non-debug builds crashed trying to import my retail pilot file which has finished the main FS2 campaign. Looking at it in gdb, missionui/redalert.cpp:red_alert_read_wingman_status expects SUBSYSTEM_MAX (13) floats for each wingman's subsys_aggregate_current_hits. My file appears to have only 12, seemingly lacking SUBSYSTEM_UNKNOWN.

The symptom is a crash slightly later in the file. My analysis, which could of course be rubbish: it appeared to be trying to read 65000 or so weapon techroom entries, having read 4 bytes too much from red alert bits for the final wingman and thus just read two techroom counts and the first few techroom values instead of the three techroom counts it was looking for. It had only survived up to that point because reading too much red alert data on the end of each non-final wingman just meant that only the name of the next wingman was affected.

The version variable was 140; my previous retail install that wrote this file was 1.2, but I don't think I had flown a mission with that pilot since patching it from what I think was 1.0 or 1.01.

My patch, which could also be rubbish, will follow. It just reads 12 subsystems rather than 13 if version is less than 142, which made everything work for me.
Steps To ReproducePlace attached pilot in data/players/single.
Launch fs2_open_r (or _d).
Choose this pilot.
Answer yes to the upgrade check.
Segfault.
TagsNo tags attached.

Activities

2007-03-08 05:21

 

cmb.plr (11,590 bytes)

cmb

2007-03-08 05:23

reporter   ~0007823

Also meant to say, I only found this project a few days ago, but I have to say, it's great so far. Thanks to all involved, let me know if there's anything else you need to know. :-)

taylor

2007-03-08 06:46

administrator   ~0007824

Last edited: 2007-03-08 07:03

SUBSYSTEM_MAX is still 12 in the stable code branch, but apparently it got bumped in HEAD so that's something that we need to address as a bigger deal. The pilot file version is going to have to be bumped to maintain compatibility with current pilot files, or the code is going to have to be removed for the time being.

Goober made the change, so let me check with him about it.

If you want to submit a patch though, that would be great. Just set the version check for >242 instead, and bump CURRENT_PLAYER_FILE_VERSION in managepilot.cpp from 242 to 243.


EDIT: Oh, and CAMPAIGN_FILE_VERSION also needs to be bumped. Also red_alert_read_wingman_status_campaign() will need to be changed so that it can take a version #, as well as check against it to handle this problem.

2007-03-08 14:45

 

pilot-file-subsys.diff (1,255 bytes)   
--- code/missionui/redalert.cpp.orig	2007-03-06 00:58:52.108008322 +0000
+++ code/missionui/redalert.cpp	2007-03-08 09:22:29.800096703 +0000
@@ -1078,6 +1078,8 @@
 	int				i, j;
 	red_alert_ship_status *ras;
 	char tname[NAME_LENGTH];
+	int				s = ( version < 243 ) ? 12
+						: SUBSYSTEM_MAX;
 
 	Red_alert_num_slots_used = cfread_int(fp);
 
@@ -1102,9 +1104,12 @@
 			ras->subsys_current_hits[j] = cfread_float(fp);
 		}
 
-		for ( j = 0; j < SUBSYSTEM_MAX; j++ ) {
+		for ( j = 0; j < s; j++ ) {
 			ras->subsys_aggregate_current_hits[j] = cfread_float(fp);
 		}
+		for ( j = s; j < SUBSYSTEM_MAX; j++ ) {
+			ras->subsys_aggregate_current_hits[j] = 0.0f;
+		}
 
 		for ( j = 0; j < MAX_SHIP_WEAPONS; j++ ) {
 			if (version >= 142) {
--- code/playerman/managepilot.cpp.orig	2007-03-08 09:23:37.977453386 +0000
+++ code/playerman/managepilot.cpp	2007-03-08 09:24:04.822836652 +0000
@@ -365,7 +365,7 @@
 
 
 // update this when altering data that is read/written to .PLR file
-#define CURRENT_PLAYER_FILE_VERSION					242
+#define CURRENT_PLAYER_FILE_VERSION					243
 #define CURRENT_MULTI_PLAYER_FILE_VERSION			142
 #define FS2_DEMO_PLAYER_FILE_VERSION				135
 #define LOWEST_COMPATIBLE_PLAYER_FILE_VERSION		140	// compatible with release - Goober5000
pilot-file-subsys.diff (1,255 bytes)   

cmb

2007-03-08 14:45

reporter   ~0007825

Oops, my earlier patch didn't make it as I didn't notice that this page has *two* forms on it, not one. :-) Anyway, the patch you described is now attached.

2007-03-25 05:17

 

1320.patch (6,061 bytes)   
Index: code/mission/missioncampaign.cpp
===================================================================
RCS file: /home/fs2source/cvsroot/fs2_open/code/mission/missioncampaign.cpp,v
retrieving revision 2.51
diff -u -p -r2.51 missioncampaign.cpp
--- code/mission/missioncampaign.cpp	21 Mar 2007 21:06:54 -0000	2.51
+++ code/mission/missioncampaign.cpp	24 Mar 2007 23:18:48 -0000
@@ -477,7 +477,8 @@ campaign Campaign;
 // bumped to 13 by Goober5000 for persistent variables
 // bumped to 14 by taylor for ship/weapon table handling
 // bumped to 15 by taylor to move stuff from pilot file
-#define CAMPAIGN_FILE_VERSION							15
+// bumped to 16 by cmb for SUBSYSTEM_MAX increment
+#define CAMPAIGN_FILE_VERSION							16
 //#define CAMPAIGN_FILE_COMPATIBLE_VERSION		CAMPAIGN_INITIAL_RELEASE_FILE_VERSION
 #define CAMPAIGN_FILE_COMPATIBLE_VERSION				12  // 12 is the version of the original FS2
 #define CAMPAIGN_FILE_ID								0xbeefcafe
@@ -1752,7 +1753,7 @@ int mission_campaign_savefile_load( char
 		pl->main_hall = cfread_ubyte(fp);
 	
 		// red-alert wingman status
-		red_alert_read_wingman_status_campaign(fp, s_name, w_name);
+		red_alert_read_wingman_status_campaign(fp, s_name, w_name, version);
 
 		// begin techroom data -------------------------------------------------
 		int intel_count;
Index: code/missionui/redalert.cpp
===================================================================
RCS file: /home/fs2source/cvsroot/fs2_open/code/missionui/redalert.cpp,v
retrieving revision 2.24
diff -u -p -r2.24 redalert.cpp
--- code/missionui/redalert.cpp	22 Mar 2007 20:47:33 -0000	2.24
+++ code/missionui/redalert.cpp	24 Mar 2007 23:18:48 -0000
@@ -1001,7 +1001,7 @@ void red_alert_bash_wingman_status()
 }
 
 // write wingman status out to the specified file
-void red_alert_write_wingman_status(CFILE *fp)
+void red_alert_write_wingman_status(CFILE *fp, ubyte is_multi)
 {
 	int				i, j;
 	red_alert_ship_status *ras;
@@ -1025,7 +1025,7 @@ void red_alert_write_wingman_status(CFIL
 			cfwrite_float(ras->subsys_current_hits[j], fp);
 		}
 
-		for ( j = 0; j < SUBSYSTEM_MAX; j++ ) {
+		for ( j = 0; j < (is_multi ? 12 : SUBSYSTEM_MAX); j++ ) {
 			cfwrite_float(ras->subsys_aggregate_current_hits[j], fp);
 		}
 
@@ -1078,6 +1078,8 @@ void red_alert_read_wingman_status(CFILE
 	int				i, j;
 	red_alert_ship_status *ras;
 	char tname[NAME_LENGTH];
+	int				s = ( version < 243 ) ? 12
+						: SUBSYSTEM_MAX;
 
 	Red_alert_num_slots_used = cfread_int(fp);
 
@@ -1102,9 +1104,12 @@ void red_alert_read_wingman_status(CFILE
 			ras->subsys_current_hits[j] = cfread_float(fp);
 		}
 
-		for ( j = 0; j < SUBSYSTEM_MAX; j++ ) {
+		for ( j = 0; j < s; j++ ) {
 			ras->subsys_aggregate_current_hits[j] = cfread_float(fp);
 		}
+		for ( j = s; j < SUBSYSTEM_MAX; j++ ) {
+			ras->subsys_aggregate_current_hits[j] = 0.0f;
+		}
 
 		for ( j = 0; j < MAX_SHIP_WEAPONS; j++ ) {
 			if (version >= 142) {
@@ -1119,11 +1124,13 @@ void red_alert_read_wingman_status(CFILE
 }
 
 // same basic thing as the above but for read from the campaign file - taylor
-void red_alert_read_wingman_status_campaign(CFILE *fp, char ships[][NAME_LENGTH], char weapons[][NAME_LENGTH])
+void red_alert_read_wingman_status_campaign(CFILE *fp, char ships[][NAME_LENGTH], char weapons[][NAME_LENGTH], int version)
 {
 	int				i, j;
 	red_alert_ship_status *ras;
 	int ras_tmp = -1;
+	int				s = ( version < 16 ) ? 12
+						: SUBSYSTEM_MAX;
 
 	Red_alert_num_slots_used = cfread_int(fp);
 
@@ -1150,9 +1157,12 @@ void red_alert_read_wingman_status_campa
 			ras->subsys_current_hits[j] = cfread_float(fp);
 		}
 
-		for ( j = 0; j < SUBSYSTEM_MAX; j++ ) {
+		for ( j = 0; j < s; j++ ) {
 			ras->subsys_aggregate_current_hits[j] = cfread_float(fp);
 		}
+		for ( j = s; j < SUBSYSTEM_MAX; j++ ) {
+			ras->subsys_aggregate_current_hits[j] = 0.0f;
+		}
 
 		for ( j = 0; j < MAX_SHIP_WEAPONS; j++ ) {
 			ras_tmp = cfread_int(fp) ;
Index: code/missionui/redalert.h
===================================================================
RCS file: /home/fs2source/cvsroot/fs2_open/code/missionui/redalert.h,v
retrieving revision 2.7
diff -u -p -r2.7 redalert.h
--- code/missionui/redalert.h	25 Jul 2005 05:24:16 -0000	2.7
+++ code/missionui/redalert.h	24 Mar 2007 23:18:48 -0000
@@ -83,6 +83,7 @@
 #define __REDALERT_H__
 
 #include "globalincs/globals.h"
+#include "globalincs/pstypes.h"
 
 struct CFILE;
 
@@ -97,12 +98,12 @@ int	red_alert_check_status();
 
 void red_alert_store_wingman_status();
 void red_alert_bash_wingman_status();
-void red_alert_write_wingman_status(CFILE *fp);
+void red_alert_write_wingman_status(CFILE *fp, ubyte is_multi = 0);
 void red_alert_read_wingman_status(CFILE *fp, int version);
 
 // campaign savefile versions
 void red_alert_write_wingman_status_campaign(CFILE *fp);
-void red_alert_read_wingman_status_campaign(CFILE *fp, char ships[][NAME_LENGTH], char weapons[][NAME_LENGTH]);
+void red_alert_read_wingman_status_campaign(CFILE *fp, char ships[][NAME_LENGTH], char weapons[][NAME_LENGTH], int version);
 
 void red_alert_voice_pause();
 void red_alert_voice_unpause();
Index: code/playerman/managepilot.cpp
===================================================================
RCS file: /home/fs2source/cvsroot/fs2_open/code/playerman/managepilot.cpp,v
retrieving revision 2.28
diff -u -p -r2.28 managepilot.cpp
--- code/playerman/managepilot.cpp	11 Feb 2007 09:31:12 -0000	2.28
+++ code/playerman/managepilot.cpp	24 Mar 2007 23:18:49 -0000
@@ -365,7 +365,7 @@
 
 
 // update this when altering data that is read/written to .PLR file
-#define CURRENT_PLAYER_FILE_VERSION					242
+#define CURRENT_PLAYER_FILE_VERSION					243
 #define CURRENT_MULTI_PLAYER_FILE_VERSION			142
 #define FS2_DEMO_PLAYER_FILE_VERSION				135
 #define LOWEST_COMPATIBLE_PLAYER_FILE_VERSION		140	// compatible with release - Goober5000
@@ -1399,7 +1399,7 @@ int write_pilot_file_core(player *p)
 	}	
 
 	if ( is_multi ) {
-		red_alert_write_wingman_status(file);
+		red_alert_write_wingman_status(file, is_multi);
 	}
 
 	pilot_write_techroom_data(file, is_multi);
1320.patch (6,061 bytes)   

cmb

2007-03-25 05:18

reporter   ~0007902

Last edited: 2007-03-25 14:20

New patch (1320.patch): adds the campaign file bump in the note edit (hadn't seen that when I sent the earlier one); also fixes multiplayer pilots, which are still written at version 142, so should only write 12 subsystems.

EDIT: Also, any pilot/campaign files already written with current CVS will need their version manually increasing to reflect the fact that they already have 13 subsystems, or this patch will crash on them. I couldn't see an easy way to detect such files.

shenlong

2007-05-14 10:03

reporter   ~0008083

I've had the same kind of problem loading a save at the end of the Freespace2 retail campaign. I probably should have checked here first, but instead it turns out I followed almost exactly the same logic as cmb to find this bug.

Here's what I first noticed:
- Segfault at loading techroom data (which appeared to be caused by the garbage 65793 value in intel_count)
- My debugger says ship_count = 113 and weapon_count = 89 in pilot_read_loadout(), but inside of pilot_read_techroom_data() ship_count = 89 and weapon_count = 10. intel_count = 10 seemed to make sense, so I suspect there was a 4-byte offset at some point while reading the file
- I poked around in redalert.cpp for a while, noticing that every ship name after the first had gotten corrupted ("Bastion" showed up fine, but "Templar" appeared as "lar" -- confirms the 4-byte offset)
- Eventually after randomly hacking away for a while, using "SUBSYSTEM_MAX - 1" in the loop inside red_alert_read_wingman_status() seemed to do the trick.

I'm writing this here since unless I've screwed up exactly the same way, cmb's report is not "rubbish" at all...

-sl

taylor

2008-07-17 16:27

administrator   ~0009458

Not going to work on this.

chief1983

2008-10-09 04:58

administrator   ~0009881

This is a problem with code that's in fs2_open-unstable and not the main trunk right?

taylor

2008-10-09 05:19

administrator   ~0009884

Correct. Pilot files are so broken in the unstable code tree that it's just plain sad. Just like 0001227, this bug is more of a reminder that said code in unstable should be worked on before it ever gets merged into the trunk.

The_E

2010-12-07 17:19

administrator   ~0012511

Closing this issue, as it doesn't seem to exist in current builds.

Issue History

Date Modified Username Field Change
2007-03-08 05:21 cmb New Issue
2007-03-08 05:21 cmb File Added: cmb.plr
2007-03-08 05:23 cmb Note Added: 0007823
2007-03-08 06:46 taylor Note Added: 0007824
2007-03-08 07:03 taylor Note Edited: 0007824
2007-03-08 14:45 cmb File Added: pilot-file-subsys.diff
2007-03-08 14:45 cmb Note Added: 0007825
2007-03-09 21:50 taylor Status new => assigned
2007-03-09 21:50 taylor Assigned To => taylor
2007-03-25 05:17 cmb File Added: 1320.patch
2007-03-25 05:18 cmb Note Added: 0007902
2007-03-25 14:20 cmb Note Edited: 0007902
2007-05-14 10:03 shenlong Note Added: 0008083
2008-07-17 16:27 taylor Note Added: 0009458
2008-07-17 16:27 taylor Assigned To taylor =>
2008-07-17 16:27 taylor Status assigned => confirmed
2008-07-17 16:27 taylor Product Version 3.6.10 =>
2008-10-09 04:58 chief1983 Note Added: 0009881
2008-10-09 05:19 taylor Note Added: 0009884
2008-10-09 05:33 chief1983 Priority normal => low
2008-10-09 05:33 chief1983 Summary Retail pilot file crash: too many subsys_aggregate_current_hits => Unstable: Retail pilot file crash: too many subsys_aggregate_current_hits
2010-12-07 17:19 The_E Note Added: 0012511
2010-12-07 17:19 The_E Status confirmed => closed
2010-12-07 17:19 The_E Resolution open => no change required