@@ -929,16 +929,45 @@ void ChallengeLoadScreen::activatePiecesMinSpec(const GeneralPersona *generalPla
929929
930930void ChallengeLoadScreen::init ( GameInfo *game )
931931{
932- const Campaign *campaign = TheCampaignManager->getCurrentCampaign ();
933- const Mission *mission = TheCampaignManager->getCurrentMission ();
932+ const Campaign *campaign = TheCampaignManager ? TheCampaignManager->getCurrentCampaign () : NULL ;
933+ const Mission *mission = TheCampaignManager ? TheCampaignManager->getCurrentMission () : NULL ;
934+
935+ // Guard against null campaign/mission. In release builds DEBUG_ASSERTCRASH is
936+ // compiled out, so without these checks the AsciiString copy constructor below
937+ // would dereference a null pointer and crash (see Sentry CLIENT-33Q).
938+ if (campaign == NULL || mission == NULL )
939+ {
940+ DEBUG_CRASH ((" ChallengeLoadScreen::init invoked with null campaign (%p) or mission (%p); aborting load." ,
941+ campaign, mission));
942+ return ;
943+ }
944+
945+ if (mission->m_generalName .isEmpty ())
946+ {
947+ DEBUG_CRASH ((" ChallengeLoadScreen::init: mission has empty m_generalName, check Campaign.ini; aborting load." ));
948+ return ;
949+ }
950+
951+ if (TheChallengeGenerals == NULL )
952+ {
953+ DEBUG_CRASH ((" ChallengeLoadScreen::init: TheChallengeGenerals is null; aborting load." ));
954+ return ;
955+ }
934956
935957 // the player general is tied to the campaign
936958 const GeneralPersona* generalPlayer = TheChallengeGenerals->getPlayerGeneralByCampaignName ( campaign->m_name );
937959
938960 // the opponent general is tied to the mission
939- DEBUG_ASSERTCRASH (mission->m_generalName .isNotEmpty (), (" No GeneralName associated with this mission, check Campaign.ini" ));
940961 const GeneralPersona* generalOpponent = TheChallengeGenerals->getGeneralByGeneralName ( mission->m_generalName );
941962
963+ if (generalPlayer == NULL || generalOpponent == NULL )
964+ {
965+ DEBUG_CRASH ((" ChallengeLoadScreen::init: failed to resolve generals (player=%p, opponent=%p) for campaign '%s' / mission general '%s'; aborting load." ,
966+ generalPlayer, generalOpponent,
967+ campaign->m_name .str (), mission->m_generalName .str ()));
968+ return ;
969+ }
970+
942971 // create the layout of the load screen
943972 m_loadScreen = TheWindowManager->winCreateFromScript ( " Menus/ChallengeLoadScreen.wnd" );
944973 DEBUG_ASSERTCRASH (m_loadScreen, (" Can't initialize the single player loadscreen" ));
@@ -953,7 +982,7 @@ void ChallengeLoadScreen::init( GameInfo *game )
953982 m_ambientLoop.setEventName (" LoadScreenAmbient" );
954983
955984 // create the new background video stream
956- m_videoStream = TheVideoPlayer->open ( TheCampaignManager-> getCurrentMission () ->m_movieLabel );
985+ m_videoStream = TheVideoPlayer->open ( mission ->m_movieLabel );
957986
958987 // Create the new buffer
959988 m_videoBuffer = TheDisplay->createVideoBuffer ();
0 commit comments