diff --git a/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp b/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp index a3235e1b69a..504a6381f28 100644 --- a/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp +++ b/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp @@ -30,5 +30,8 @@ AudioRequest::~AudioRequest() { - + if (m_usePendingEvent) + { + delete m_pendingEvent; + } } diff --git a/Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp index c002ff8f239..7519684a572 100644 --- a/Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp +++ b/Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp @@ -262,16 +262,36 @@ void GameLogic::clearGameData( Bool showScoreScreen ) TheScriptActions->closeWindows(FALSE); // Close victory or defeat windows. Bool shellGame = FALSE; - if ((!isInShellGame() || !isInGame()) && showScoreScreen && !TheGlobalData->m_headless) + if (showScoreScreen) { - shellGame = TRUE; - TheTransitionHandler->setGroup("FadeWholeScreen"); - TheShell->push("Menus/ScoreScreen.wnd"); - TheShell->showShell(FALSE); // by passing in false, we don't want to run the Init on the shell screen we just pushed on - TheTransitionHandler->reverse("FadeWholeScreen"); - - void FixupScoreScreenMovieWindow(); - FixupScoreScreenMovieWindow(); + if ((!isInShellGame() || !isInGame()) && !TheGlobalData->m_headless) + { + shellGame = TRUE; + TheTransitionHandler->setGroup("FadeWholeScreen"); + TheShell->push("Menus/ScoreScreen.wnd"); + TheShell->showShell(FALSE); // by passing in false, we don't want to run the Init on the shell screen we just pushed on + TheTransitionHandler->reverse("FadeWholeScreen"); + + void FixupScoreScreenMovieWindow(); + FixupScoreScreenMovieWindow(); + + destroyQuitMenu(); + } + + // TheSuperHackers @info The game info may have been allocated on save game load. + // Deallocate it here until there's a better place to do it. + if (TheSkirmishGameInfo) + { + delete TheSkirmishGameInfo; + TheSkirmishGameInfo = nullptr; + TheGameInfo = nullptr; + } + else if (TheChallengeGameInfo) + { + delete TheChallengeGameInfo; + TheChallengeGameInfo = nullptr; + TheGameInfo = nullptr; + } } TheGameEngine->reset(); diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 3a541494959..3e1a832dca9 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -2236,6 +2236,11 @@ void MilesAudioManager::processRequestList() if (!req->m_requiresCheckForSample || checkForSample(req)) { processRequest(req); + + // TheSuperHackers @info Deallocating the audio event is no longer responsibility of this request, + // because it was just processed. Reset fields to avoid use after free and double free. + req->m_usePendingEvent = false; + req->m_pendingEvent = nullptr; } deleteInstance(req); it = m_audioRequests.erase(it); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp index d5d1fd7f292..3b46fe5a5e4 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp @@ -2180,51 +2180,53 @@ void W3DModelDraw::adjustAnimation(const ModelConditionInfo* prevState, Real pre const W3DAnimationInfo& animInfo = m_curState->m_animations[m_whichAnimInCurState]; - HAnimClass* animHandle = animInfo.getAnimHandle(); // note that this now returns an ADDREFED handle, which must be released by the caller! - if (m_renderObject && animHandle) + if (m_renderObject) { - Int startFrame = 0; - if (m_curState->m_mode == RenderObjClass::ANIM_MODE_ONCE_BACKWARDS || - m_curState->m_mode == RenderObjClass::ANIM_MODE_LOOP_BACKWARDS) + HAnimClass* animHandle = animInfo.getAnimHandle(); // note that this now returns an ADDREFED handle, which must be released by the caller! + if (animHandle) { - startFrame = animHandle->Get_Num_Frames()-1; - } + Int startFrame = 0; + if (m_curState->m_mode == RenderObjClass::ANIM_MODE_ONCE_BACKWARDS || + m_curState->m_mode == RenderObjClass::ANIM_MODE_LOOP_BACKWARDS) + { + startFrame = animHandle->Get_Num_Frames()-1; + } - if (testFlagBit(m_curState->m_flags, RANDOMIZE_START_FRAME)) - { - startFrame = GameClientRandomValue(0, animHandle->Get_Num_Frames()-1); - } - else if (testFlagBit(m_curState->m_flags, START_FRAME_FIRST)) - { - startFrame = 0; - } - else if (testFlagBit(m_curState->m_flags, START_FRAME_LAST)) - { - startFrame = animHandle->Get_Num_Frames()-1; - } - // order is important here: MAINTAIN_FRAME_ACROSS_STATES is overridden by the other bits, above. - else if (isAnyMaintainFrameFlagSet(m_curState->m_flags) && - prevState && - prevState != m_curState && - isAnyMaintainFrameFlagSet(prevState->m_flags) && - isCommonMaintainFrameFlagSet(m_curState->m_flags, prevState->m_flags) && - prevAnimFraction >= 0.0) - { - startFrame = REAL_TO_INT(prevAnimFraction * animHandle->Get_Num_Frames()-1); - } + if (testFlagBit(m_curState->m_flags, RANDOMIZE_START_FRAME)) + { + startFrame = GameClientRandomValue(0, animHandle->Get_Num_Frames()-1); + } + else if (testFlagBit(m_curState->m_flags, START_FRAME_FIRST)) + { + startFrame = 0; + } + else if (testFlagBit(m_curState->m_flags, START_FRAME_LAST)) + { + startFrame = animHandle->Get_Num_Frames()-1; + } + // order is important here: MAINTAIN_FRAME_ACROSS_STATES is overridden by the other bits, above. + else if (isAnyMaintainFrameFlagSet(m_curState->m_flags) && + prevState && + prevState != m_curState && + isAnyMaintainFrameFlagSet(prevState->m_flags) && + isCommonMaintainFrameFlagSet(m_curState->m_flags, prevState->m_flags) && + prevAnimFraction >= 0.0) + { + startFrame = REAL_TO_INT(prevAnimFraction * animHandle->Get_Num_Frames()-1); + } - m_renderObject->Set_Animation(animHandle, startFrame, m_curState->m_mode); - REF_PTR_RELEASE(animHandle); - animHandle = nullptr; + m_renderObject->Set_Animation(animHandle, startFrame, m_curState->m_mode); + REF_PTR_RELEASE(animHandle); + animHandle = nullptr; - if (m_renderObject->Class_ID() == RenderObjClass::CLASSID_HLOD) - { - HLodClass *hlod = (HLodClass*)m_renderObject; - Real factor = GameClientRandomValueReal( m_curState->m_animMinSpeedFactor, m_curState->m_animMaxSpeedFactor ); - hlod->Set_Animation_Frame_Rate_Multiplier( factor ); + if (m_renderObject->Class_ID() == RenderObjClass::CLASSID_HLOD) + { + HLodClass *hlod = (HLodClass*)m_renderObject; + Real factor = GameClientRandomValueReal( m_curState->m_animMinSpeedFactor, m_curState->m_animMaxSpeedFactor ); + hlod->Set_Animation_Frame_Rate_Multiplier( factor ); + } } } - } else { diff --git a/Core/Libraries/Source/WWVegas/WW3D2/hcanim.cpp b/Core/Libraries/Source/WWVegas/WW3D2/hcanim.cpp index 704898a8875..3bc866b7517 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/hcanim.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/hcanim.cpp @@ -293,10 +293,6 @@ int HCompressedAnimClass::Load_W3D(ChunkLoadClass & cload) /* ** Now, read in all of the other chunks (motion channels). */ - TimeCodedMotionChannelClass * tc_chan; - AdaptiveDeltaMotionChannelClass * ad_chan; - TimeCodedBitChannelClass * newbitchan; - while (cload.Open_Chunk()) { switch (cload.Cur_Chunk_ID()) { @@ -306,7 +302,8 @@ int HCompressedAnimClass::Load_W3D(ChunkLoadClass & cload) switch ( Flavor ) { case ANIM_FLAVOR_TIMECODED: - + { + TimeCodedMotionChannelClass* tc_chan = nullptr; if (!read_channel(cload,&tc_chan)) { goto Error; } @@ -322,8 +319,11 @@ int HCompressedAnimClass::Load_W3D(ChunkLoadClass & cload) } break; + } case ANIM_FLAVOR_ADAPTIVE_DELTA: + { + AdaptiveDeltaMotionChannelClass* ad_chan = nullptr; if (!read_channel(cload,&ad_chan)) { goto Error; } @@ -338,10 +338,13 @@ int HCompressedAnimClass::Load_W3D(ChunkLoadClass & cload) WWDEBUG_SAY(("ERROR! animation %s indexes a bone not present in the model. Please re-export!",Name)); } break; + } } break; case W3D_CHUNK_COMPRESSED_BIT_CHANNEL: + { + TimeCodedBitChannelClass* newbitchan = nullptr; if (!read_bit_channel(cload,&newbitchan)) { goto Error; } @@ -357,6 +360,7 @@ int HCompressedAnimClass::Load_W3D(ChunkLoadClass & cload) } break; + } default: break; @@ -387,20 +391,32 @@ int HCompressedAnimClass::Load_W3D(ChunkLoadClass & cload) *=============================================================================================*/ bool HCompressedAnimClass::read_channel(ChunkLoadClass & cload,TimeCodedMotionChannelClass * * newchan) { - *newchan = W3DNEW TimeCodedMotionChannelClass; - bool result = (*newchan)->Load_W3D(cload); - - return result; - + TimeCodedMotionChannelClass* channel = W3DNEW TimeCodedMotionChannelClass; + if (channel->Load_W3D(cload)) + { + *newchan = channel; + return true; + } + else + { + delete channel; + return false; + } } bool HCompressedAnimClass::read_channel(ChunkLoadClass & cload,AdaptiveDeltaMotionChannelClass * * newchan) { - *newchan = W3DNEW AdaptiveDeltaMotionChannelClass; - bool result = (*newchan)->Load_W3D(cload); - - return result; - + AdaptiveDeltaMotionChannelClass* channel = W3DNEW AdaptiveDeltaMotionChannelClass; + if (channel->Load_W3D(cload)) + { + *newchan = channel; + return true; + } + else + { + delete channel; + return false; + } } @@ -483,11 +499,17 @@ void HCompressedAnimClass::add_channel(AdaptiveDeltaMotionChannelClass * newchan *=============================================================================================*/ bool HCompressedAnimClass::read_bit_channel(ChunkLoadClass & cload,TimeCodedBitChannelClass * * newchan) { - *newchan = W3DNEW TimeCodedBitChannelClass; - bool result = (*newchan)->Load_W3D(cload); - - return result; - + TimeCodedBitChannelClass* channel = W3DNEW TimeCodedBitChannelClass; + if (channel->Load_W3D(cload)) + { + *newchan = channel; + return true; + } + else + { + delete channel; + return false; + } } diff --git a/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp b/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp index 681c4c0b0fa..9b5970062ee 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/seglinerenderer.cpp @@ -191,7 +191,7 @@ void SegLineRendererClass::Set_Texture_Tile_Factor(float factor) ///@todo: I raised this number and didn't see much difference on our min-spec. -MW const static float MAX_LINE_TILING_FACTOR = 50.0f; if (factor > MAX_LINE_TILING_FACTOR) { - WWDEBUG_SAY(("Texture (%s) Tile Factor (%.2f) too large in SegLineRendererClass!", Get_Texture()->Get_Texture_Name().str(), TextureTileFactor)); + WWDEBUG_SAY(("Texture (%s) Tile Factor (%.2f) too large in SegLineRendererClass!", Peek_Texture()->Get_Texture_Name().str(), TextureTileFactor)); factor = MAX_LINE_TILING_FACTOR; } else { factor = MAX(factor, 0.0f); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp index a9a53e3a006..b7b5e5edc6a 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -3167,13 +3167,13 @@ void Player::removeUpgrade( const UpgradeTemplate *upgradeTemplate ) if( upgrade->getStatus() == UPGRADE_STATUS_COMPLETE ) onUpgradeRemoved(); - if( ThePlayerList->getLocalPlayer() == this ) - { - TheControlBar->markUIDirty(); - } + deleteInstance(upgrade); + if( ThePlayerList->getLocalPlayer() == this ) + { + TheControlBar->markUIDirty(); + } } - } diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameStateMap.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameStateMap.cpp index b2c4d3fba4c..f503e975f8c 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameStateMap.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameStateMap.cpp @@ -104,6 +104,8 @@ static void embedPristineMap( AsciiString map, Xfer *xfer ) if( file->read( buffer, fileSize ) != fileSize ) { + delete[] buffer; + DEBUG_CRASH(( "embedPristineMap - Error reading from file '%s'", map.str() )); throw SC_INVALID_DATA; @@ -161,6 +163,8 @@ static void embedInUseMap( AsciiString map, Xfer *xfer ) if( fread( buffer, 1, fileSize, fp ) != fileSize ) { + delete[] buffer; + DEBUG_CRASH(( "embedInUseMap - Error reading from file '%s'", map.str() )); throw SC_INVALID_DATA; @@ -216,6 +220,8 @@ static void extractAndSaveMap( AsciiString mapToSave, Xfer *xfer ) if( fwrite( buffer, 1, dataSize, fp ) != dataSize ) { + delete[] buffer; + DEBUG_CRASH(( "extractAndSaveMap - Error writing to file '%s'", mapToSave.str() )); throw SC_INVALID_DATA; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp index 40abef67afe..da55dbbf2d4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp @@ -116,17 +116,13 @@ static_assert(ARRAY_SIZE(TheDrawableIconNames) == MAX_ICONS + 1, "Incorrect arra * * OK, so it's a bit of a hack, but it saves memory in every Drawable */ -static DynamicAudioEventInfo * getNoSoundMarker() -{ - static DynamicAudioEventInfo * marker = nullptr; +class DynamicAudioEventInfoStatic : public DynamicAudioEventInfo +{}; +static DynamicAudioEventInfoStatic s_noSoundMarker; - if ( marker == nullptr ) - { - // Initialize first time function is called - marker = newInstance( DynamicAudioEventInfo ); - } - - return marker; +static DynamicAudioEventInfo* getNoSoundMarker() +{ + return &s_noSoundMarker; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp index 679ee2160f3..b2c05e49597 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp @@ -544,7 +544,12 @@ void SidesList::prepareForMP_or_Skirmish() break; } } - if (curSide == -1) continue; + if (curSide == -1) + { + deleteInstance(scripts[i]); + scripts[i] = nullptr; + continue; + } deleteInstance(getSkirmishSideInfo(curSide)->getScriptList()); getSkirmishSideInfo(curSide)->setScriptList(scripts[i]); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp index d4d0cead9dd..333d39662c1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp @@ -164,6 +164,7 @@ BattlePlanUpdate::~BattlePlanUpdate() TheAudio->removeAudioEvent( m_holdTheLineUnpack.getPlayingHandle() ); TheAudio->removeAudioEvent( m_holdTheLinePack.getPlayingHandle() ); + deleteInstance(m_bonuses); } // ------------------------------------------------------------------------------------------------ diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hrawanim.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hrawanim.cpp index 54fdfb732e3..377e813236e 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hrawanim.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hrawanim.cpp @@ -236,14 +236,13 @@ int HRawAnimClass::Load_W3D(ChunkLoadClass & cload) /* ** Now, read in all of the other chunks (motion channels). */ - MotionChannelClass * newchan; - BitChannelClass * newbitchan; - while (cload.Open_Chunk()) { switch (cload.Cur_Chunk_ID()) { case W3D_CHUNK_ANIMATION_CHANNEL: + { + MotionChannelClass* newchan = nullptr; if (!read_channel(cload,&newchan,pre30)) { goto Error; } @@ -258,8 +257,11 @@ int HRawAnimClass::Load_W3D(ChunkLoadClass & cload) delete newchan; } break; + } case W3D_CHUNK_BIT_CHANNEL: + { + BitChannelClass* newbitchan = nullptr; if (!read_bit_channel(cload,&newbitchan,pre30)) { goto Error; } @@ -274,6 +276,7 @@ int HRawAnimClass::Load_W3D(ChunkLoadClass & cload) delete newbitchan; } break; + } default: break; @@ -304,15 +307,22 @@ int HRawAnimClass::Load_W3D(ChunkLoadClass & cload) *=============================================================================================*/ bool HRawAnimClass::read_channel(ChunkLoadClass & cload,MotionChannelClass * * newchan,bool pre30) { - *newchan = W3DNEW MotionChannelClass; - bool result = (*newchan)->Load_W3D(cload); + MotionChannelClass* channel = W3DNEW MotionChannelClass; + if (channel->Load_W3D(cload)) + { + if (pre30) + { + channel->Set_Pivot(channel->Get_Pivot() + 1); + } - if (result && pre30) { -// (*newchan)->PivotIdx += 1; - (*newchan)->Set_Pivot((*newchan)->Get_Pivot()+1); + *newchan = channel; + return true; + } + else + { + delete channel; + return false; } - - return result; } /*********************************************************************************************** @@ -379,14 +389,22 @@ void HRawAnimClass::add_channel(MotionChannelClass * newchan) *=============================================================================================*/ bool HRawAnimClass::read_bit_channel(ChunkLoadClass & cload,BitChannelClass * * newchan,bool pre30) { - *newchan = W3DNEW BitChannelClass; - bool result = (*newchan)->Load_W3D(cload); + BitChannelClass* channel = W3DNEW BitChannelClass; + if (channel->Load_W3D(cload)) + { + if (pre30) + { + channel->PivotIdx += 1; + } - if (result && pre30) { - (*newchan)->PivotIdx += 1; + *newchan = channel; + return true; + } + else + { + delete channel; + return false; } - - return result; } diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp index fd36b02b024..27af92ec44a 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp @@ -1584,6 +1584,9 @@ void ScriptDialog::OnLoad() msg += m_readPlayerNames[i].str(); msg += ", discarding scripts for this player."; ::AfxMessageBox(msg); + + deleteInstance(scripts[i]); + scripts[i] = nullptr; continue; } } @@ -1591,8 +1594,8 @@ void ScriptDialog::OnLoad() curSide = 0; ::AfxMessageBox("Imported scripts came from more players than exist in this map. Additional scripts moved to Neutral player."); } - ScriptList *pSL = m_sides.getSideInfo(curSide)->getScriptList(); + ScriptList *pSL = m_sides.getSideInfo(curSide)->getScriptList(); if (pSL) { Script *pScr; Script *pNextScr; @@ -1616,8 +1619,10 @@ void ScriptDialog::OnLoad() copied into the current scripts. */ scripts[i] = nullptr; //reloadPlayer(curSide, pSL); + } else { + deleteInstance(scripts[i]); + scripts[i] = nullptr; } - } for (i = 0; i < m_sides.getNumSides(); i++) {