-
Notifications
You must be signed in to change notification settings - Fork 77
[GEN][ZH] Fix heap-use-after-free in W3DRadar::drawHeroIcon() #1035
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
** Command & Conquer Generals Zero Hour(tm) | ||
** Copyright 2025 TheSuperHackers | ||
** | ||
** This program is free software: you can redistribute it and/or modify | ||
** it under the terms of the GNU General Public License as published by | ||
** the Free Software Foundation, either version 3 of the License, or | ||
** (at your option) any later version. | ||
** | ||
** This program is distributed in the hope that it will be useful, | ||
** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
** GNU General Public License for more details. | ||
** | ||
** You should have received a copy of the GNU General Public License | ||
** along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <Utility/CppMacros.h> | ||
#include <utility> | ||
|
||
namespace stl | ||
{ | ||
|
||
// Finds first matching element in vector-like container and erases it. | ||
template <typename Container> | ||
bool find_and_erase(Container& container, const typename Container::value_type& value) | ||
{ | ||
typename Container::const_iterator it = container.begin(); | ||
for (; it != container.end(); ++it) | ||
{ | ||
if (*it == value) | ||
{ | ||
container.erase(it); | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
// Finds first matching element in vector-like container and removes it by swapping it with the last element. | ||
// This is generally faster than erasing from a vector, but will change the element sorting. | ||
template <typename Container> | ||
bool find_and_erase_unordered(Container& container, const typename Container::value_type& value) | ||
{ | ||
typename Container::iterator it = container.begin(); | ||
for (; it != container.end(); ++it) | ||
{ | ||
if (*it == value) | ||
{ | ||
*it = CPP_11(std::move)(container.back()); | ||
container.pop_back(); | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
} // namespace stl |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,9 @@ class W3DRadar : public Radar | |
virtual void update( void ); ///< subsystem update | ||
virtual void reset( void ); ///< subsystem reset | ||
|
||
virtual bool addObject( Object *obj ); ///< add object to radar | ||
virtual bool removeObject( Object *obj ); ///< remove object from radar | ||
|
||
virtual void newMap( TerrainLogic *terrain ); ///< reset radar for new map | ||
|
||
void draw( Int pixelX, Int pixelY, Int width, Int height ); ///< draw the radar | ||
|
@@ -80,7 +83,7 @@ class W3DRadar : public Radar | |
void drawViewBox( Int pixelX, Int pixelY, Int width, Int height ); ///< draw view box | ||
void buildTerrainTexture( TerrainLogic *terrain ); ///< create the terrain texture of the radar | ||
void drawIcons( Int pixelX, Int pixelY, Int width, Int height ); ///< draw all of the radar icons | ||
void renderObjectList( const RadarObject *listHead, TextureClass *texture, Bool calcHero = FALSE ); ///< render an object list to the texture | ||
void renderObjectList( const RadarObject *listHead, TextureClass *texture ); ///< render an object list to the texture | ||
void interpolateColorForHeight( RGBColor *color, | ||
Real height, | ||
Real hiZ, | ||
|
@@ -118,7 +121,7 @@ class W3DRadar : public Radar | |
Real m_viewZoom; ///< camera zoom used for the view box we have | ||
ICoord2D m_viewBox[ 4 ]; ///< radar cell points for the 4 corners of view box | ||
|
||
std::list<const Coord3D *> m_cachedHeroPosList; //< cache of hero positions for drawing icons in radar overlay | ||
std::vector<const Object *> m_cachedHeroObjectList; //< cache of hero objects for drawing icons in radar overlay | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed the container type here because list of coordinate pointers is not particularly great. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be better to change to Changes:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The position changes when the Hero moves. Putting a fixed position into the vector would paint the radar icon at a static position. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it would. I just tried it and the position is not fixed on the radar. It wouldn't be if the position is updated each frame; i.e. if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect you test with calcHero code? The calcHero rebuilds the vector every now and then. This change does not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, sorry. |
||
}; | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this change, this resetAll crashed on map unload in
The problem is that the Object's TunnelContain module has a dependency on the player, but the player was already purged from the PlayerList. And so this would crash.
Resetting GameLogic first avoids this (and potentially similar issues in the future). Alternatively we could add more NULL checks in TunnelContain, but I think that is not necessary if Subsystem just have a proper reset sequence.