From a44781bd73d440628a096f4e79e4dbc27cbcc590 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Thu, 15 Jul 2021 05:15:52 +0200 Subject: [PATCH] :bug: Fix bounds checks in monster code --- Source/missiles.cpp | 9 ++-- Source/monster.cpp | 121 +++++++++++++++++++++----------------------- Source/msg.cpp | 2 +- 3 files changed, 65 insertions(+), 67 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 1b2c493c4..1b0164ed3 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1485,7 +1485,7 @@ void AddBerserk(int mi, Point /*src*/, Point dst, int /*midir*/, int8_t /*mienem int dm = dMonster[tx][ty]; dm = dm > 0 ? dm - 1 : -(dm + 1); - if (dm <= 3) + if (dm < MAX_PLRS) continue; auto &monster = Monsters[dm]; @@ -2233,7 +2233,7 @@ void AddLightning(int mi, Point /*src*/, Point dst, int midir, int8_t mienemy, i void AddMisexp(int mi, Point /*src*/, Point dst, int /*midir*/, int8_t mienemy, int id, int /*dam*/) { - if (mienemy != 0 && id > 0) { + if (mienemy != 0 && id >= 0) { switch (Monsters[id].MType->mtype) { case MT_SUCCUBUS: SetMissAnim(mi, MFILE_FLAREEXP); @@ -2597,6 +2597,8 @@ void AddStone(int mi, Point /*src*/, Point dst, int /*midir*/, int8_t /*mienemy* ty = dst.y + CrawlTable[ck]; if (InDungeonBounds({ tx, ty })) { int mid = dMonster[tx][ty]; + if (mid == 0) + continue; mid = mid > 0 ? mid - 1 : -(mid + 1); auto &monster = Monsters[mid]; if (mid > MAX_PLRS - 1 && monster._mAi != AI_DIABLO && monster.MType->mtype != MT_NAKRUL) { @@ -3481,7 +3483,8 @@ void MI_HorkSpawn(int mi) i = 6; auto md = static_cast(Missiles[mi]._miVar1); int monsterId = AddMonster({ tx, ty }, md, 1, true); - M_StartStand(Monsters[monsterId], md); + if (monsterId != -1) + M_StartStand(Monsters[monsterId], md); break; } } diff --git a/Source/monster.cpp b/Source/monster.cpp index f48595643..3527f94cd 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1957,13 +1957,14 @@ void GroupUnity(int i) assert((DWORD)i < MAXMONSTERS); auto &monster = Monsters[i]; - auto &leader = Monsters[monster.leader]; - if (monster.leaderflag != MonsterRelation::Individual) { - bool clear = IsLineNotSolid(monster.position.tile, leader.position.future); - if (clear || monster.leaderflag != MonsterRelation::Minion) { - if (clear - && monster.leaderflag == MonsterRelation::Leader - && monster.position.tile.WalkingDistance(leader.position.future) < 4) { + if (monster.leaderflag == MonsterRelation::Individual) { + return; + } + + if (monster.leader != 0) { + auto &leader = Monsters[monster.leader]; + if (IsLineNotSolid(monster.position.tile, leader.position.future)) { + if (monster.leaderflag == MonsterRelation::Leader && monster.position.tile.WalkingDistance(leader.position.future) < 4) { leader.packsize++; monster.leaderflag = MonsterRelation::Minion; } @@ -1971,35 +1972,34 @@ void GroupUnity(int i) leader.packsize--; monster.leaderflag = MonsterRelation::Leader; } - } - if (monster.leaderflag == MonsterRelation::Minion) { - if (monster._msquelch > leader._msquelch) { - leader.position.last = monster.position.tile; - leader._msquelch = monster._msquelch - 1; - } - if (leader._mAi == AI_GARG) { - if ((leader._mFlags & MFLAG_ALLOW_SPECIAL) != 0) { - leader._mFlags &= ~MFLAG_ALLOW_SPECIAL; - leader._mmode = MM_SATTACK; + if (monster.leaderflag == MonsterRelation::Minion) { + if (monster._msquelch > leader._msquelch) { + leader.position.last = monster.position.tile; + leader._msquelch = monster._msquelch - 1; } } - } else if (monster._uniqtype != MonsterRelation::Individual) { - if ((UniqMonst[monster._uniqtype - 1].mUnqAttr & 2) != 0) { - for (int j = 0; j < ActiveMonsterCount; j++) { - auto &minion = Monsters[ActiveMonsters[j]]; - if (minion.leaderflag == MonsterRelation::Minion && minion.leader == i) { - if (monster._msquelch > minion._msquelch) { - minion.position.last = monster.position.tile; - minion._msquelch = monster._msquelch - 1; - } - if (minion._mAi == AI_GARG) { - if ((minion._mFlags & MFLAG_ALLOW_SPECIAL) != 0) { - minion._mFlags &= ~MFLAG_ALLOW_SPECIAL; - minion._mmode = MM_SATTACK; - } - } - } + } + + if (monster._mAi == AI_GARG && (monster._mFlags & MFLAG_ALLOW_SPECIAL) != 0) { + if (monster.leaderflag == MonsterRelation::Minion || monster.packsize > 0) { + monster._mFlags &= ~MFLAG_ALLOW_SPECIAL; + monster._mmode = MM_SATTACK; + } + } + + if (monster.leaderflag == MonsterRelation::Leader && monster._uniqtype != 0) { + if ((UniqMonst[monster._uniqtype - 1].mUnqAttr & 2) == 0) { + return; + } + for (int j = 0; j < ActiveMonsterCount; j++) { + auto &minion = Monsters[ActiveMonsters[j]]; + if (minion.leaderflag != MonsterRelation::Minion || minion.leader != i) { + continue; + } + if (monster._msquelch > minion._msquelch) { + minion.position.last = monster.position.tile; + minion._msquelch = monster._msquelch - 1; } } } @@ -4386,38 +4386,35 @@ void GolumAi(int i) if ((golem._mFlags & MFLAG_TARGETS_MONSTER) == 0) UpdateEnemy(golem); - bool haveEnemy = (golem._mFlags & MFLAG_NO_ENEMY) == 0; - if (golem._mmode == MM_ATTACK) { return; } - auto &enemy = Monsters[golem._menemy]; - - int mex = golem.position.tile.x - enemy.position.future.x; - int mey = golem.position.tile.y - enemy.position.future.y; - Direction md = GetDirection(golem.position.tile, enemy.position.tile); - golem._mdir = md; - if (abs(mex) < 2 && abs(mey) < 2 && haveEnemy) { - golem.enemyPosition = enemy.position.tile; - if (enemy._msquelch == 0) { - enemy._msquelch = UINT8_MAX; - enemy.position.last = golem.position.tile; - for (int j = 0; j < 5; j++) { - for (int k = 0; k < 5; k++) { - int menemy = dMonster[golem.position.tile.x + k - 2][golem.position.tile.y + j - 2]; // BUGFIX: Check if indexes are between 0 and 112 - if (menemy > 0) - Monsters[menemy - 1]._msquelch = UINT8_MAX; // BUGFIX: should be `Monsters[_menemy-1]`, not Monsters[_menemy]. (fixed) + if ((golem._mFlags & MFLAG_NO_ENEMY) == 0) { + auto &enemy = Monsters[golem._menemy]; + int mex = golem.position.tile.x - enemy.position.future.x; + int mey = golem.position.tile.y - enemy.position.future.y; + golem._mdir = GetDirection(golem.position.tile, enemy.position.tile); + if (abs(mex) < 2 && abs(mey) < 2) { + golem.enemyPosition = enemy.position.tile; + if (enemy._msquelch == 0) { + enemy._msquelch = UINT8_MAX; + enemy.position.last = golem.position.tile; + for (int j = 0; j < 5; j++) { + for (int k = 0; k < 5; k++) { + int enemyId = dMonster[golem.position.tile.x + k - 2][golem.position.tile.y + j - 2]; // BUGFIX: Check if indexes are between 0 and 112 + if (enemyId > 0) + Monsters[enemyId - 1]._msquelch = UINT8_MAX; // BUGFIX: should be `Monsters[_menemy-1]`, not Monsters[_menemy]. (fixed) + } } } + StartAttack(golem); + return; } - StartAttack(golem); - return; + if (AiPlanPath(i)) + return; } - if (haveEnemy && AiPlanPath(i)) - return; - golem._pathcount++; if (golem._pathcount > 8) golem._pathcount = 5; @@ -4426,7 +4423,7 @@ void GolumAi(int i) if (ok) return; - md = left[md]; + Direction md = left[golem._mdir]; for (int j = 0; j < 8 && !ok; j++) { md = right[md]; ok = DirOK(i, md); @@ -4628,12 +4625,10 @@ bool DirOK(int i, Direction mdir) if (y < 0 || y >= MAXDUNY || x < 0 || x >= MAXDUNX) continue; int mi = dMonster[x][y]; - if (mi < 0) - mi = -mi; - if (mi != 0) - mi--; - // BUGFIX: should only run pack member check if mi was non-zero prior to executing the body of the above if-statement. - auto &minion = Monsters[mi]; + if (mi == 0) + continue; + + auto &minion = Monsters[(mi < 0) ? -(mi + 1) : (mi - 1)]; if (minion.leaderflag == MonsterRelation::Minion && minion.leader == i && minion.position.future == Point { x, y }) { diff --git a/Source/msg.cpp b/Source/msg.cpp index 06e6c14b7..c99d685f7 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1264,7 +1264,7 @@ DWORD OnMonstDeath(TCmd *pCmd, int pnum) if (gbBufferMsgs == 1) SendPacket(pnum, p, sizeof(*p)); - else if (pnum != MyPlayerId) { + else if (pnum != MyPlayerId && p->wParam1 < MAXMONSTERS) { if (currlevel == Players[pnum].plrlevel) M_SyncStartKill(p->wParam1, { p->x, p->y }, pnum); delta_kill_monster(p->wParam1, { p->x, p->y }, Players[pnum].plrlevel);