From 3d1980710dc3a717188f39542659d3b76e4d3c60 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Mon, 24 Aug 2026 02:47:56 +0300
Subject: [PATCH 54/54] savegame: Fix Out-of-Bounds Read in activities.order[]

Reported by Tristan

See RM #2162

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 server/savegame/savegame2.c | 10 ++++++++--
 server/savegame/savegame3.c | 11 +++++++++--
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c
index 6b2df30ef1..e55adcea17 100644
--- a/server/savegame/savegame2.c
+++ b/server/savegame/savegame2.c
@@ -4297,11 +4297,17 @@ static bool sg_load_player_unit(struct loaddata *loading,
   sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->fuel,
                                      "%s.fuel", unitstr), FALSE,
                   "%s", secfile_error());
+
   sg_warn_ret_val(secfile_lookup_int(loading->file, &ei,
                                      "%s.activity", unitstr), FALSE,
                   "%s", secfile_error());
-  activity = unit_activity_by_name(loading->activities.order[ei],
-                                   fc_strcasecmp);
+  if (ei >= 0 && ei < loading->activities.size) {
+    activity = unit_activity_by_name(loading->activities.order[ei],
+                                     fc_strcasecmp);
+  } else {
+    log_sg("Invalid activity id for unit %d", punit->id);
+    activity = ACTIVITY_IDLE;
+  }
 
   punit->birth_turn
     = secfile_lookup_int_default(loading->file, game.info.turn,
diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c
index ed3f0caad8..3de74e23ad 100644
--- a/server/savegame/savegame3.c
+++ b/server/savegame/savegame3.c
@@ -6227,11 +6227,18 @@ static bool sg_load_player_unit(struct loaddata *loading,
   sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->fuel,
                                      "%s.fuel", unitstr), FALSE,
                   "%s", secfile_error());
+
   sg_warn_ret_val(secfile_lookup_int(loading->file, &ei,
                                      "%s.activity", unitstr), FALSE,
                   "%s", secfile_error());
-  activity = unit_activity_by_name(loading->activities.order[ei],
-                                   fc_strcasecmp);
+  if (ei >= 0 && ei < loading->activities.size) {
+    activity = unit_activity_by_name(loading->activities.order[ei],
+                                     fc_strcasecmp);
+  } else {
+    log_sg("Invalid activity id for unit %d", punit->id);
+    activity = ACTIVITY_IDLE;
+  }
+
   sg_warn_ret_val(secfile_lookup_int(loading->file, &ei,
                                      "%s.action", unitstr), FALSE,
                   "%s", secfile_error());
-- 
2.53.0

