[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