shp_nav_gauntlet() and lnd_mar_gauntlet() read beyond the list head
when the list is empty. The values read aren't used then. Could
conceivably crash the server anyway, but it's unlikely.
Empty list happens when shp_nav_dir(), lnd_mar_dir() empty the list
and return zero. Broken in commit
beedf8d, v4.3.33. Occurs in
navi-march-test (since the last commit) and in retreat-test.
Change shp_nav_dir() and lnd_mar_dir() to return one then. For
additional safety, make shp_nav_gauntlet() and lnd_mar_gauntlet() oops
on empty list and recover safely.
I think I originally found this bug with -fsanitize, but I've since
upgraded, and I can't diagnose it that way anymore.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
}
}
- return 0;
+ return QEMPTY(list);
}
int
lnd_mar_gauntlet(struct emp_qelem *list, int interdict, natid actor)
{
struct ulist *mlp = (struct ulist *)list->q_back;
- coord newx = mlp->unit.land.lnd_x;
- coord newy = mlp->unit.land.lnd_y;
+ coord newx, newy;
int stopping, visible;
struct emp_qelem *qp, *next;
struct ulist *llp;
+ if (CANT_HAPPEN(QEMPTY(list)))
+ return 1;
+ newx = mlp->unit.land.lnd_x;
+ newy = mlp->unit.land.lnd_y;
stopping = lnd_sweep(list, 0, 1, actor);
if (QEMPTY(list))
- return stopping;
+ return 1;
stopping |= lnd_check_mines(list);
if (QEMPTY(list))
- return stopping;
+ return 1;
visible = 0;
for (qp = list->q_back; qp != list; qp = next) {
putship(mlp->unit.ship.shp_uid, &mlp->unit.ship);
}
- return 0;
+ return QEMPTY(list);
}
int
shp_nav_gauntlet(struct emp_qelem *list, int interdict, natid actor)
{
struct ulist *mlp = (struct ulist *)list->q_back;
- coord newx = mlp->unit.ship.shp_x;
- coord newy = mlp->unit.ship.shp_y;
+ coord newx, newy;
int stopping;
+ if (CANT_HAPPEN(QEMPTY(list)))
+ return 1;
+ newx = mlp->unit.ship.shp_x;
+ newy = mlp->unit.ship.shp_y;
stopping = shp_sweep(list, 0, 0, actor);
if (QEMPTY(list))
- return stopping;
+ return 1;
stopping |= shp_check_mines(list);
if (QEMPTY(list))
- return stopping;
+ return 1;
if (interdict)
stopping |= shp_interdict(list, newx, newy, actor);