[freeciv/f13/master] fix stealth fighter crash #628649
thomasj
thomasj at fedoraproject.org
Tue Aug 31 10:12:22 UTC 2010
commit 9795fe9d7c558cc193616b192b989f255690f185
Author: Thomas Janssen <thomasj at fedoraproject.org>
Date: Tue Aug 31 12:12:20 2010 +0200
fix stealth fighter crash #628649
freeciv.spec | 17 +++-
stealth_fighter_fix-1.patch | 25 +++++
stealth_fighter_fix-2.patch | 244 +++++++++++++++++++++++++++++++++++++++++++
stealth_fighter_fix-3.patch | 101 ++++++++++++++++++
stealth_fighter_fix-4.patch | 23 ++++
stealth_fighter_fix-5.patch | 24 ++++
stealth_fighter_fix-6.patch | 20 ++++
7 files changed, 453 insertions(+), 1 deletions(-)
---
diff --git a/freeciv.spec b/freeciv.spec
index a8fcf31..c08edeb 100644
--- a/freeciv.spec
+++ b/freeciv.spec
@@ -5,7 +5,7 @@
Name: freeciv
Version: 2.2.2
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: A multi-player strategy game
Group: Amusements/Games
@@ -16,6 +16,12 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
##Fix DSO patch
Patch10: freeciv-client-fix-DSO.patch
+Patch20: stealth_fighter_fix-1.patch
+Patch30: stealth_fighter_fix-2.patch
+Patch40: stealth_fighter_fix-3.patch
+Patch50: stealth_fighter_fix-4.patch
+Patch60: stealth_fighter_fix-5.patch
+Patch70: stealth_fighter_fix-6.patch
BuildRequires: gtk2-devel
BuildRequires: readline-devel
@@ -42,6 +48,12 @@ in order to become the leader of the greatest civilization.
%prep
%setup -q -n %{name}-%{version}
%patch10 -p0
+%patch20 -p0
+%patch30 -p0
+%patch40 -p0
+%patch50 -p0
+%patch60 -p0
+%patch70 -p0
%build
%configure --enable-client=gtk --disable-static
@@ -110,6 +122,9 @@ fi
%changelog
+* Tue Aug 31 2010 Thomas Janssen <thomasj at fedoraproject.org> 2.2.2-2
+- fix stealth fighter crash #628649
+
* Mon Aug 02 2010 Thomas Janssen <thomasj at fedoraproject.org> 2.2.2-1
- security fix https://www.redhat.com/security/data/cve/CVE-2010-2445.html
- fixes #612296
diff --git a/stealth_fighter_fix-1.patch b/stealth_fighter_fix-1.patch
new file mode 100644
index 0000000..c9bea4e
--- /dev/null
+++ b/stealth_fighter_fix-1.patch
@@ -0,0 +1,25 @@
+--- server/citytools.c (révision 17882)
++++ server/citytools.c (copie de travail)
+@@ -912,10 +912,8 @@
+ new_vision = vision_new(ptaker, pcenter);
+ pcity->server.vision = new_vision;
+ vision_reveal_tiles(new_vision, game.info.vision_reveal_tiles);
+- vision_layer_iterate(v) {
+- vision_change_sight(new_vision, v,
+- vision_get_sight(old_vision, v));
+- } vision_layer_iterate_end;
++ vision_change_sight(new_vision, vision_get_sight(old_vision, V_MAIN),
++ vision_get_sight(old_vision, V_INVIS));
+
+ ASSERT_VISION(new_vision);
+
+@@ -2488,8 +2486,7 @@
+ {
+ int radius_sq = get_city_bonus(pcity, EFT_CITY_VISION_RADIUS_SQ);
+
+- vision_change_sight(pcity->server.vision, V_MAIN, radius_sq);
+- vision_change_sight(pcity->server.vision, V_INVIS, 2);
++ vision_change_sight(pcity->server.vision, radius_sq, 2);
+
+ ASSERT_VISION(pcity->server.vision);
+ }
diff --git a/stealth_fighter_fix-2.patch b/stealth_fighter_fix-2.patch
new file mode 100644
index 0000000..8ecc551
--- /dev/null
+++ b/stealth_fighter_fix-2.patch
@@ -0,0 +1,244 @@
+--- server/maphand.c 2010-07-25 21:53:39.000000000 +0200
++++ server/maphand.c.old 2010-08-30 21:16:58.000000000 +0200
+@@ -635,33 +635,57 @@
+ } players_iterate_end;
+ }
+
+-/**************************************************************************
+- There doesn't have to be a city.
+-**************************************************************************/
+-void map_refog_circle(struct player *pplayer, struct tile *ptile,
+- int old_radius_sq, int new_radius_sq,
+- bool can_reveal_tiles,
+- enum vision_layer vlayer)
++/****************************************************************************
++ Really refog the circle for the vision layer.
++****************************************************************************/
++static void real_map_refog_circle(struct player *pplayer, struct tile *ptile,
++ int old_radius_sq, int new_radius_sq,
++ bool can_reveal_tiles,
++ enum vision_layer vlayer)
+ {
+ if (old_radius_sq != new_radius_sq) {
+ int max_radius = MAX(old_radius_sq, new_radius_sq);
+
+ freelog(LOG_DEBUG, "Refogging circle at %d,%d from %d to %d",
+- TILE_XY(ptile), old_radius_sq, new_radius_sq);
++ TILE_XY(ptile), old_radius_sq, new_radius_sq);
+
+ buffer_shared_vision(pplayer);
+ circle_dxyr_iterate(ptile, max_radius, tile1, dx, dy, dr) {
+ if (dr > old_radius_sq && dr <= new_radius_sq) {
+- map_unfog_tile(pplayer, tile1, can_reveal_tiles, vlayer);
++ map_unfog_tile(pplayer, tile1, can_reveal_tiles, vlayer);
+ } else if (dr > new_radius_sq && dr <= old_radius_sq) {
+- map_fog_tile(pplayer, tile1, vlayer);
++ map_fog_tile(pplayer, tile1, vlayer);
+ }
+ } circle_dxyr_iterate_end;
+ unbuffer_shared_vision(pplayer);
+ }
+ }
++/****************************************************************************
++ There doesn't have to be a city.
++ FIXME: results would be unexpected if the new_invis_radius_sq is bigger
++ than new_main_radius_sq.
++****************************************************************************/
++void map_refog_circle(struct player *pplayer, struct tile *ptile,
++ int old_main_radius_sq, int new_main_radius_sq,
++ int old_invis_radius_sq, int new_invis_radius_sq,
++ bool can_reveal_tiles)
++{
++ if (new_invis_radius_sq < old_invis_radius_sq) {
++ /* Then remove the invisible units first for the clients. */
++ real_map_refog_circle(pplayer, ptile, old_invis_radius_sq,
++ new_invis_radius_sq, can_reveal_tiles, V_INVIS);
++ real_map_refog_circle(pplayer, ptile, old_main_radius_sq,
++ new_main_radius_sq, can_reveal_tiles, V_MAIN);
++ } else {
++ real_map_refog_circle(pplayer, ptile, old_main_radius_sq,
++ new_main_radius_sq, can_reveal_tiles, V_MAIN);
++ real_map_refog_circle(pplayer, ptile, old_invis_radius_sq,
++ new_invis_radius_sq, can_reveal_tiles, V_INVIS);
++ }
++}
+
+ /****************************************************************************
++/****************************************************************************
+ Shows the area to the player. Unless the tile is "seen", it will remain
+ fogged and units will be hidden.
+
+@@ -740,14 +764,16 @@
+ remove_dumb_city(pplayer, ptile);
+
+ if (map_get_seen(ptile, pplayer, V_MAIN) > 0) {
+- /* Remove units. */
+- vision_layer_iterate(v) {
++ /* Remove units. Using unit_list_iterate or
++ * unit_list_reverse_iterate is equivalent here, because the
++ * tile info is sent after all units went out of sight. */
++ vision_layer_reverse_iterate(v) {
+ unit_list_iterate(ptile->units, punit) {
+ if (unit_is_visible_on_layer(punit, v)) {
+ unit_goes_out_of_sight(pplayer, punit);
+ }
+ } unit_list_iterate_end;
+- } vision_layer_iterate_end;
++ } vision_layer_reverse_iterate_end;
+ }
+ }
+
+@@ -909,11 +935,14 @@
+ void map_clear_known(struct tile *ptile, struct player *pplayer)
+ {
+ BV_CLR(ptile->tile_known, player_index(pplayer));
+- vision_layer_iterate(v) {
++ /* Using vision_layer_iterate or vision_layer_reverse_iterate
++ * is equivalent here, because no units are going out of sight, neither
++ * the tile info is sent to the client. */
++ vision_layer_reverse_iterate(v) {
+ if (0 == map_get_player_tile(ptile, pplayer)->seen_count[v]) {
+ BV_CLR(ptile->tile_seen[v], player_index(pplayer));
+ }
+- } vision_layer_iterate_end;
++ } vision_layer_reverse_iterate_end;
+ }
+
+ /****************************************************************************
+@@ -1332,7 +1361,7 @@
+ player_name(pplayer),
+ player_name(pplayer2));
+ whole_map_iterate(ptile) {
+- vision_layer_iterate(v) {
++ vision_layer_reverse_iterate(v) {
+ int change = map_get_own_seen(ptile, pplayer, v);
+
+ if (change > 0) {
+@@ -1340,7 +1369,7 @@
+ if (map_get_seen(ptile, pplayer2, v) == 0)
+ really_fog_tile(pplayer2, ptile, v);
+ }
+- } vision_layer_iterate_end;
++ } vision_layer_reverse_iterate_end;
+ } whole_map_iterate_end;
+ }
+ } players_iterate_end;
+@@ -1609,27 +1638,18 @@
+ if (ploser != powner) {
+ base_type_iterate(pbase) {
+ if (tile_has_base(ptile, pbase)) {
+- if (pbase->vision_main_sq >= 0) {
+- /* Transfer base provided vision to new owner */
+- if (powner) {
+- map_refog_circle(powner, ptile, -1, pbase->vision_main_sq,
+- game.info.vision_reveal_tiles, V_MAIN);
+- }
+- if (ploser && pbase != ignore_loss) {
+- map_refog_circle(ploser, ptile, pbase->vision_main_sq, -1,
+- game.info.vision_reveal_tiles, V_MAIN);
+- }
++ /* Transfer base provided vision to new owner */
++ if (powner) {
++ map_refog_circle(powner, ptile,
++ -1, pbase->vision_main_sq,
++ -1, pbase->vision_invis_sq,
++ game.info.vision_reveal_tiles);
+ }
+- if (pbase->vision_invis_sq >= 0) {
+- /* Transfer base provided vision to new owner */
+- if (powner) {
+- map_refog_circle(powner, ptile, -1, pbase->vision_invis_sq,
+- game.info.vision_reveal_tiles, V_INVIS);
+- }
+- if (ploser && pbase != ignore_loss) {
+- map_refog_circle(ploser, ptile, pbase->vision_invis_sq, -1,
+- game.info.vision_reveal_tiles, V_INVIS);
+- }
++ if (ploser && pbase != ignore_loss) {
++ map_refog_circle(ploser, ptile,
++ pbase->vision_main_sq, -1,
++ pbase->vision_invis_sq, -1,
++ game.info.vision_reveal_tiles);
+ }
+ }
+ } base_type_iterate_end;
+@@ -1764,13 +1784,15 @@
+
+ See documentation in vision.h.
+ ****************************************************************************/
+-void vision_change_sight(struct vision *vision, enum vision_layer vlayer,
+- int radius_sq)
++void vision_change_sight(struct vision *vision, int radius_main_sq,
++ int radius_invis_sq)
+ {
+ map_refog_circle(vision->player, vision->tile,
+- vision->radius_sq[vlayer], radius_sq,
+- vision->can_reveal_tiles, vlayer);
+- vision->radius_sq[vlayer] = radius_sq;
++ vision->radius_sq[V_MAIN], radius_main_sq,
++ vision->radius_sq[V_INVIS], radius_invis_sq,
++ vision->can_reveal_tiles);
++ vision->radius_sq[V_MAIN] = radius_main_sq;
++ vision->radius_sq[V_INVIS] = radius_invis_sq;
+ }
+
+ /****************************************************************************
+@@ -1780,10 +1802,7 @@
+ ****************************************************************************/
+ void vision_clear_sight(struct vision *vision)
+ {
+- /* We don't use vision_layer_iterate because we have to go in reverse
+- * order. */
+- vision_change_sight(vision, V_INVIS, -1);
+- vision_change_sight(vision, V_MAIN, -1);
++ vision_change_sight(vision, -1, -1);
+ }
+
+ /****************************************************************************
+@@ -1801,14 +1820,16 @@
+ } else {
+ struct player *owner = tile_owner(ptile);
+
+- if (old_base->vision_main_sq >= 0 && owner) {
++ if (NULL != owner
++ && (0 <= old_base->vision_main_sq
++ || 0 <= old_base->vision_invis_sq)) {
+ /* Base provides vision, but no borders. */
+- map_refog_circle(owner, ptile, old_base->vision_main_sq, -1,
+- game.info.vision_reveal_tiles, V_MAIN);
+- }
+- if (old_base->vision_invis_sq >= 0 && owner) {
+- map_refog_circle(owner, ptile, old_base->vision_invis_sq, -1,
+- game.info.vision_reveal_tiles, V_INVIS);
++ map_refog_circle(owner, ptile,
++ 0 <= old_base->vision_main_sq
++ ? old_base->vision_main_sq : -1, -1,
++ 0 <= old_base->vision_invis_sq
++ ? old_base->vision_invis_sq : -1, -1,
++ game.info.vision_reveal_tiles);
+ }
+ }
+ tile_remove_base(ptile, old_base);
+@@ -1830,13 +1851,15 @@
+ } else {
+ struct player *owner = tile_owner(ptile);
+
+- if (pbase->vision_main_sq > 0 && owner) {
+- map_refog_circle(owner, ptile, -1, pbase->vision_main_sq,
+- game.info.vision_reveal_tiles, V_MAIN);
+- }
+- if (pbase->vision_invis_sq > 0 && owner) {
+- map_refog_circle(owner, ptile, -1, pbase->vision_invis_sq,
+- game.info.vision_reveal_tiles, V_INVIS);
++ if (NULL != owner
++ && (0 < pbase->vision_main_sq
++ || 0 < pbase->vision_invis_sq)) {
++ map_refog_circle(owner, ptile,
++ -1, 0 < pbase->vision_main_sq
++ ? pbase->vision_main_sq : -1,
++ -1, 0 < pbase->vision_invis_sq
++ ? pbase->vision_invis_sq : -1,
++ game.info.vision_reveal_tiles);
+ }
+ }
+ }
diff --git a/stealth_fighter_fix-3.patch b/stealth_fighter_fix-3.patch
new file mode 100644
index 0000000..2feb5cd
--- /dev/null
+++ b/stealth_fighter_fix-3.patch
@@ -0,0 +1,101 @@
+--- server/maphand.h (révision 17882)
++++ server/maphand.h (copie de travail)
+@@ -64,9 +64,9 @@
+ void map_show_circle(struct player *pplayer,
+ struct tile *ptile, int radius_sq);
+ void map_refog_circle(struct player *pplayer, struct tile *ptile,
+- int old_radius_sq, int new_radius_sq,
+- bool can_reveal_tiles,
+- enum vision_layer vlayer);
++ int old_main_radius_sq, int new_main_radius_sq,
++ int old_invis_radius_sq, int new_invis_radius_sq,
++ bool can_reveal_tiles);
+ void map_show_all(struct player *pplayer);
+
+ bool map_is_known_and_seen(const struct tile *ptile, struct player *pplayer,
+@@ -113,8 +113,8 @@
+ void fix_tile_on_terrain_change(struct tile *ptile,
+ bool extend_rivers);
+
+-void vision_change_sight(struct vision *vision, enum vision_layer vlayer,
+- int radius_sq);
++void vision_change_sight(struct vision *vision, int radius_main_sq,
++ int radius_invis_sq);
+ void vision_clear_sight(struct vision *vision);
+
+ void change_playertile_site(struct player_tile *ptile,
+Index: server/unittools.c
+===================================================================
+--- server/unittools.c (révision 17882)
++++ server/unittools.c (copie de travail)
+@@ -625,16 +625,17 @@
+ } else {
+ struct player *owner = tile_owner(ptile);
+
+- if (pbase->vision_main_sq >= 0 && owner) {
+- /* Base provides vision, but no borders. */
+- map_refog_circle(owner, ptile, pbase->vision_main_sq, -1,
+- game.info.vision_reveal_tiles, V_MAIN);
++ if (NULL != owner
++ && (0 <= pbase->vision_main_sq)
++ && (0 <= pbase->vision_invis_sq)) {
++ /* Base provides vision, but no borders. */
++ map_refog_circle(owner, ptile,
++ 0 <= pbase->vision_main_sq
++ ? pbase->vision_main_sq : -1, -1,
++ 0 <= pbase->vision_invis_sq
++ ? pbase->vision_invis_sq : -1, -1,
++ game.info.vision_reveal_tiles);
+ }
+- if (pbase->vision_invis_sq >= 0 && owner) {
+- /* Base provides vision, but no borders. */
+- map_refog_circle(owner, ptile, pbase->vision_invis_sq, -1,
+- game.info.vision_reveal_tiles, V_INVIS);
+- }
+ }
+ tile_remove_base(ptile, pbase);
+ }
+@@ -2860,10 +2861,9 @@
+ struct vision *new_vision = vision_new(unit_owner(pcargo), pdesttile);
+
+ pcargo->server.vision = new_vision;
+- vision_layer_iterate(v) {
+- vision_change_sight(new_vision, v,
+- get_unit_vision_at(pcargo, pdesttile, v));
+- } vision_layer_iterate_end;
++ vision_change_sight(new_vision,
++ get_unit_vision_at(pcargo, pdesttile, V_MAIN),
++ get_unit_vision_at(pcargo, pdesttile, V_INVIS));
+
+ ASSERT_VISION(new_vision);
+
+@@ -2899,10 +2899,9 @@
+ if (unit_lives) {
+ new_vision = vision_new(unit_owner(punit), pdesttile);
+ punit->server.vision = new_vision;
+- vision_layer_iterate(v) {
+- vision_change_sight(new_vision, v,
+- get_unit_vision_at(punit, pdesttile, v));
+- } vision_layer_iterate_end;
++ vision_change_sight(new_vision,
++ get_unit_vision_at(punit, pdesttile, V_MAIN),
++ get_unit_vision_at(punit, pdesttile, V_INVIS));
+
+ ASSERT_VISION(new_vision);
+
+@@ -3428,12 +3427,9 @@
+ {
+ struct vision *uvision = punit->server.vision;
+
+- vision_layer_iterate(v) {
+- /* This requires two calls to get_unit_vision_at...it could be
+- * optimized. */
+- vision_change_sight(uvision, v,
+- get_unit_vision_at(punit, punit->tile, v));
+- } vision_layer_iterate_end;
++ vision_change_sight(uvision,
++ get_unit_vision_at(punit, punit->tile, V_MAIN),
++ get_unit_vision_at(punit, punit->tile, V_INVIS));
+
+ ASSERT_VISION(uvision);
+ }
diff --git a/stealth_fighter_fix-4.patch b/stealth_fighter_fix-4.patch
new file mode 100644
index 0000000..5b2a564
--- /dev/null
+++ b/stealth_fighter_fix-4.patch
@@ -0,0 +1,23 @@
+--- server/savegame.c (révision 17882)
++++ server/savegame.c (copie de travail)
+@@ -5020,14 +5020,12 @@
+ if (owner) {
+ base_type_iterate(pbase) {
+ if (tile_has_base(ptile, pbase)) {
+- if (pbase->vision_main_sq > 0) {
+- map_refog_circle(owner, ptile, -1, pbase->vision_main_sq,
+- game.info.vision_reveal_tiles, V_MAIN);
+- }
+- if (pbase->vision_invis_sq > 0) {
+- map_refog_circle(owner, ptile, -1, pbase->vision_invis_sq,
+- game.info.vision_reveal_tiles, V_INVIS);
+- }
++ map_refog_circle(owner, ptile,
++ -1, 0 < pbase->vision_main_sq
++ ? pbase->vision_main_sq : -1,
++ -1, 0 < pbase->vision_invis_sq
++ ? pbase->vision_invis_sq : -1,
++ game.info.vision_reveal_tiles);
+ }
+ } base_type_iterate_end;
+ }
diff --git a/stealth_fighter_fix-5.patch b/stealth_fighter_fix-5.patch
new file mode 100644
index 0000000..2759683
--- /dev/null
+++ b/stealth_fighter_fix-5.patch
@@ -0,0 +1,24 @@
+--- common/vision.h (révision 17882)
++++ common/vision.h (copie de travail)
+@@ -104,7 +104,21 @@
+ } \
+ }
+
++/* Using vision_layer_iterate at server side is dangerous when fogging
++ * tiles because it iterates V_MAIN first, able to crash the clients in
++ * handle_tile_info() in client/packhand.c on a failed assertion if the
++ * tile info is received before the units on the V_INVIS layer aren't gone
++ * out sight yet. */
++#define vision_layer_reverse_iterate(vision) \
++{ \
++ int vision = V_COUNT - 1; \
++ for (; vision >= 0; vision--) {
+
++#define vision_layer_reverse_iterate_end \
++ } \
++}
++
++
+ /* This is copied in maphand.c really_give_tile_info_from_player_to_player(),
+ * so be careful with pointers!
+ */
diff --git a/stealth_fighter_fix-6.patch b/stealth_fighter_fix-6.patch
new file mode 100644
index 0000000..37aecbf
--- /dev/null
+++ b/stealth_fighter_fix-6.patch
@@ -0,0 +1,20 @@
+--- client/packhand.c (révision 17882)
++++ client/packhand.c (copie de travail)
+@@ -2531,7 +2531,7 @@
+
+ if (TILE_KNOWN_SEEN == old_known && TILE_KNOWN_SEEN != new_known) {
+ /* This is an error. So first we log the error, then make an assertion.
+- * But for NDEBUG clients we fix the error. */
++ * But for non DEBUG clients we fix the error. */
+ unit_list_iterate(ptile->units, punit) {
+ freelog(LOG_ERROR, "%p %d %s at (%d,%d) %s",
+ punit,
+@@ -2540,7 +2540,9 @@
+ TILE_XY(punit->tile),
+ player_name(unit_owner(punit)));
+ } unit_list_iterate_end;
++#ifdef DEBUG
+ assert(unit_list_size(ptile->units) == 0);
++#endif /* DEBUG */
+ unit_list_clear(ptile->units);
+ }
More information about the scm-commits
mailing list