Author: sveinung
Date: Sun Aug 16 10:37:37 2015
New Revision: 29541

URL: http://svn.gna.org/viewcvs/freeciv?rev=29541&view=rev
Log:
Validate action id range

Check that each action id loaded from a save game or received over the
network is valid.

See patch #6235

Modified:
    trunk/client/packhand.c
    trunk/server/savegame3.c
    trunk/server/unithand.c

Modified: trunk/client/packhand.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/packhand.c?rev=29541&r1=29540&r2=29541&view=diff
==============================================================================
--- trunk/client/packhand.c     (original)
+++ trunk/client/packhand.c     Sun Aug 16 10:37:37 2015
@@ -233,6 +233,10 @@
       punit->orders.list[i].activity = packet->orders_activities[i];
       punit->orders.list[i].target = packet->orders_targets[i];
       punit->orders.list[i].action = packet->orders_actions[i];
+
+      /* Just an assert. The client doesn't use the action data. */
+      fc_assert(punit->orders.list[i].order != ORDER_PERFORM_ACTION
+                || action_id_is_valid(punit->orders.list[i].action));
     }
   }
 
@@ -3576,6 +3580,16 @@
 {
   struct action *act;
 
+  /* Action id is currently hard coded in the gen_action enum. It is
+   * therefore OK to use action_id_is_valid() */
+  if (!action_id_is_valid(p->id)) {
+    /* Action id out of range */
+    log_error("handle_ruleset_action() the action id %d is out of range.",
+              p->id);
+
+    return;
+  }
+
   act = action_by_number(p->id);
 
   sz_strlcpy(act->ui_name, p->ui_name);
@@ -3589,6 +3603,15 @@
 {
   struct action_enabler *enabler;
   int i;
+
+  if (!action_id_is_valid(p->enabled_action)) {
+    /* Non existing action */
+    log_error("handle_ruleset_action_enabler() the action %d "
+              "doesn't exist.",
+              p->enabled_action);
+
+    return;
+  }
 
   enabler = action_enabler_new();
 
@@ -3959,6 +3982,9 @@
 
 /**************************************************************************
   Handle the requested follow up question about an action
+
+  The action can be a valid action or the special value ACTION_COUNT.
+  ACTION_COUNT indicates that performing the action is impossible.
 **************************************************************************/
 void handle_unit_action_answer(int diplomat_id, int target_id, int cost,
                                enum gen_action action_type)
@@ -3967,6 +3993,16 @@
   struct unit *punit = game_unit_by_number(target_id);
   struct unit *pdiplomat = player_unit_by_number(client_player(),
                                                  diplomat_id);
+
+  if (ACTION_COUNT != action_type
+      && !action_id_is_valid(action_type)) {
+    /* Non existing action */
+    log_error("handle_unit_action_answer() the action %d doesn't exist.",
+              action_type);
+
+    choose_action_queue_next();
+    return;
+  }
 
   if (!pdiplomat) {
     log_debug("Bad actor %d.", diplomat_id);

Modified: trunk/server/savegame3.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/savegame3.c?rev=29541&r1=29540&r2=29541&view=diff
==============================================================================
--- trunk/server/savegame3.c    (original)
+++ trunk/server/savegame3.c    Sun Aug 16 10:37:37 2015
@@ -5174,6 +5174,8 @@
 
         if (order->order == ORDER_LAST
             || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
+            || (order->order == ORDER_PERFORM_ACTION
+                && !action_id_is_valid(order->action))
             || (order->order == ORDER_ACTIVITY
                 && order->activity == ACTIVITY_LAST)) {
           /* An invalid order. Just drop the orders for this unit. */

Modified: trunk/server/unithand.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/unithand.c?rev=29541&r1=29540&r2=29541&view=diff
==============================================================================
--- trunk/server/unithand.c     (original)
+++ trunk/server/unithand.c     Sun Aug 16 10:37:37 2015
@@ -1199,6 +1199,15 @@
   struct unit *punit = game_unit_by_number(target_id);
   struct city *pcity = game_city_by_number(target_id);
 
+  if (!action_id_is_valid(action_type)) {
+    /* Non existing action */
+    log_error("handle_unit_action_query() the action %d doesn't exist.",
+              action_type);
+
+    unit_query_impossible(pc, actor_id, target_id);
+    return;
+  }
+
   if (NULL == pactor) {
     /* Probably died or bribed. */
     log_verbose("handle_unit_action_query() invalid actor %d",
@@ -1285,6 +1294,10 @@
   Execute a request to perform an action and let the caller know if it was
   performed or not.
 
+  The action can be a valid action or the special value ACTION_MOVE.
+  ACTION_MOVE will move the unit even if it may be able to perform an
+  action against something at the target tile.
+
   Returns TRUE iff action could be done, FALSE if it couldn't. Even if
   this returns TRUE, unit may have died during the action.
 **************************************************************************/
@@ -1299,6 +1312,15 @@
   struct tile *target_tile = index_to_tile(target_id);
   struct unit *punit = game_unit_by_number(target_id);
   struct city *pcity = game_city_by_number(target_id);
+
+  if (!(action_type == ACTION_MOVE
+        || action_id_is_valid(action_type))) {
+    /* Non existing action */
+    log_error("unit_perform_action() the action %d doesn't exist.",
+              action_type);
+
+    return FALSE;
+  }
 
   if (NULL == actor_unit) {
     /* Probably died or bribed. */
@@ -3630,6 +3652,16 @@
 
       break;
     case ORDER_PERFORM_ACTION:
+      if (!action_id_is_valid(packet->action[i])) {
+        /* Non existing action */
+        log_error("handle_unit_orders() the action %d doesn't exist. "
+                  "Sent in order number %d from %s to unit number %d.",
+                  packet->action[i], i,
+                  player_name(pplayer), packet->unit_id);
+
+        return;
+      }
+
       switch ((enum gen_action) packet->action[i]) {
       case ACTION_FOUND_CITY:
         if (is_valid_dir(packet->dir[i])) {


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to