Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2003:
[Freeciv-Dev] Re: (PR#4761) civserver get_invention crash
Home

[Freeciv-Dev] Re: (PR#4761) civserver get_invention crash

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: chrisk@xxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#4761) civserver get_invention crash
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 6 Aug 2003 14:44:59 -0700
Reply-to: rt@xxxxxxxxxxxxxx

This is caused by the F_UNDISBANDABLE flag.  When such a unit cannot be 
supported a unit of population is taken from the city instead.  Nobody 
checks to see if this causes the city to disband.  Random memory 
corruption can result.

The attached patch should fix this particular instance.  However I 
suspect all callers of city_reduce_size should check the return value.

jason

? core.10353
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.218
diff -u -r1.218 cityturn.c
--- server/cityturn.c   2003/08/04 15:42:47     1.218
+++ server/cityturn.c   2003/08/06 21:42:52
@@ -56,7 +56,7 @@
 static bool worklist_change_build_target(struct player *pplayer,
                                         struct city *pcity);
 
-static void city_distribute_surplus_shields(struct player *pplayer,
+static bool city_distribute_surplus_shields(struct player *pplayer,
                                            struct city *pcity);
 static bool city_build_building(struct player *pplayer, struct city *pcity);
 static bool city_build_unit(struct player *pplayer, struct city *pcity);
@@ -427,14 +427,15 @@
 }
 
 /**************************************************************************
-...
+  Reduce the city size.  Return TRUE if the city survives the population
+  loss.
 **************************************************************************/
-void city_reduce_size(struct city *pcity, int pop_loss)
+bool city_reduce_size(struct city *pcity, int pop_loss)
 {
   if (pcity->size <= pop_loss) {
     remove_city_from_minimap(pcity->x, pcity->y);
     remove_city(pcity);
-    return;
+    return FALSE;
   }
   pcity->size -= pop_loss;
 
@@ -465,6 +466,8 @@
     auto_arrange_workers(pcity);
     sync_cities();
   }
+
+  return TRUE;
 }
 
 /**************************************************************************
@@ -890,9 +893,10 @@
 }
 
 /**************************************************************************
-  Disband units if we don't have enough shields to support them.
+  Disband units if we don't have enough shields to support them.  Returns
+  FALSE if the _city_ is disbanded as a result.
 **************************************************************************/
-static void city_distribute_surplus_shields(struct player *pplayer,
+static bool city_distribute_surplus_shields(struct player *pplayer,
                                            struct city *pcity)
 {
   struct government *g = get_gov_pplayer(pplayer);
@@ -918,7 +922,9 @@
        notify_player_ex(pplayer, pcity->x, pcity->y, E_UNIT_LOST,
                         _("Game: Citizens in %s perish for their failure to "
                         "upkeep %s!"), pcity->name, unit_type(punit)->name);
-        city_reduce_size(pcity, 1);
+       if (!city_reduce_size(pcity, 1)) {
+         return FALSE;
+       }
        break;
       }
     }
@@ -928,6 +934,8 @@
   /* Now we confirm changes made last turn. */
   pcity->shield_stock += pcity->shield_surplus;
   pcity->before_change_shields = pcity->shield_stock;
+
+  return TRUE;
 }
 
 /**************************************************************************
@@ -1138,7 +1146,9 @@
 **************************************************************************/
 static bool city_build_stuff(struct player *pplayer, struct city *pcity)
 {
-  city_distribute_surplus_shields(pplayer, pcity);
+  if (!city_distribute_surplus_shields(pplayer, pcity)) {
+    return FALSE;
+  }
   nullify_caravan_and_disband_plus(pcity);
 
   if (!pcity->is_building_unit) {
Index: server/cityturn.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.h,v
retrieving revision 1.28
diff -u -r1.28 cityturn.h
--- server/cityturn.h   2002/12/18 17:36:20     1.28
+++ server/cityturn.h   2003/08/06 21:42:52
@@ -27,7 +27,7 @@
 void auto_arrange_workers(struct city *pcity); /* will arrange the workers */
 void add_adjust_workers(struct city *pcity);   /* will add workers */
 
-void city_reduce_size(struct city *pcity, int pop_loss);
+bool city_reduce_size(struct city *pcity, int pop_loss);
 void send_global_city_turn_notifications(struct conn_list *dest);
 void send_city_turn_notifications(struct conn_list *dest, struct city *pcity);
 void begin_cities_turn(struct player *pplayer);

[Prev in Thread] Current Thread [Next in Thread]