From 49b43f760f5b85011577743530cf867cbc8e91ab Mon Sep 17 00:00:00 2001 From: copperwater Date: Sat, 8 Mar 2025 07:47:28 -0500 Subject: [PATCH] Fix: a number of unblock_points shouldn't unblock unconditionally Initially diagnosed in an xnethack fuzzer crash - unblock_point shouldn't be called when a closed door becomes non-closed, because it's possible that there's a gas cloud on the space which means it still blocks vision. These always need to be recalc_block_point. A number of them were fixed, but when I went through all the xnethack ones, I found some that were unchanged from upstream NetHack. I reproduced the sanity check impossibles usually by breathing gas at a door as an iron golem and then opening or destroying the door to trigger the unblock_point call. The use of recalc_block_point in wizterrainwish was not triggering this bug, but the previous code there basically duplicated recalc_block_point. --- src/dig.c | 2 +- src/dokick.c | 2 +- src/hack.c | 2 +- src/music.c | 2 +- src/objnam.c | 9 +-------- src/trap.c | 2 +- 6 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/dig.c b/src/dig.c index 195222235..fabafac7b 100644 --- a/src/dig.c +++ b/src/dig.c @@ -1435,7 +1435,7 @@ mdig_tunnel(struct monst *mtmp) sawit = canseemon(mtmp); /* before door state change and unblock_pt */ trapped = (here->doormask & D_TRAPPED) ? TRUE : FALSE; here->doormask = trapped ? D_NODOOR : D_BROKEN; - unblock_point(mtmp->mx, mtmp->my); /* vision */ + recalc_block_point(mtmp->mx, mtmp->my); /* vision */ newsym(mtmp->mx, mtmp->my); if (trapped) { seeit = canseemon(mtmp); diff --git a/src/dokick.c b/src/dokick.c index cf8bb405b..45d0b097c 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -949,7 +949,7 @@ kick_door(coordxy x, coordxy y, int avrg_attrib) gm.maploc->doormask = D_BROKEN; } feel_newsym(x, y); /* we know we broke it */ - unblock_point(x, y); /* vision */ + recalc_block_point(x, y); /* vision */ if (shopdoor) { add_damage(x, y, SHOP_DOOR_COST); pay_for_damage("break", FALSE); diff --git a/src/hack.c b/src/hack.c index f28877e47..71d252af5 100644 --- a/src/hack.c +++ b/src/hack.c @@ -787,7 +787,7 @@ still_chewing(coordxy x, coordxy y) lev->typ = CORR; } - unblock_point(x, y); /* vision */ + recalc_block_point(x, y); /* vision */ newsym(x, y); if (digtxt) You1(digtxt); /* after newsym */ diff --git a/src/music.c b/src/music.c index ca8c64f31..21614860d 100644 --- a/src/music.c +++ b/src/music.c @@ -463,7 +463,7 @@ do_earthquake(int force) } /* wasn't doorless, now it will be */ levl[x][y].doormask = D_NODOOR; - unblock_point(x, y); + recalc_block_point(x, y); newsym(x, y); /* before pline */ if (cansee(x, y)) pline_The("door collapses."); diff --git a/src/objnam.c b/src/objnam.c index 4463a12bb..3a1cba698 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -3862,14 +3862,7 @@ wizterrainwish(struct _readobjnam_data *d) } else { if (u.utrap && u.utraptype == TT_LAVA && !is_lava(u.ux, u.uy)) reset_utrap(FALSE); - - if (does_block(x, y, lev)) { - if (!didblock) - block_point(x, y); - } else { - if (didblock) - unblock_point(x, y); - } + recalc_block_point(x, y); } /* fixups for replaced terrain that aren't handled above */ diff --git a/src/trap.c b/src/trap.c index f309dd595..934020cd1 100644 --- a/src/trap.c +++ b/src/trap.c @@ -3443,7 +3443,7 @@ launch_obj( } levl[x][y].doormask = D_BROKEN; if (dist) - unblock_point(x, y); + recalc_block_point(x, y); } /* if about to hit something, do so now */