diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a0dac4c34..81e0c36fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Bug #5870: Disposing of actors who were selected in the console doesn't deselect them like vanilla Bug #5883: Immobile creatures don't cause water ripples Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load + Bug #6025: Subrecords cannot overlap records Bug #6027: Collisionshape becomes spiderweb-like when the mesh is too complex Bug #6313: Followers with high Fight can turn hostile Bug #6427: Enemy health bar disappears before damaging effect ends diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index 3e480b8f5e..b602bbd253 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -342,10 +342,7 @@ namespace ESM getUint(mCtx.leftSub); mCtx.leftRec -= sizeof(mCtx.leftSub); - // Adjust number of record bytes left - if (mCtx.leftRec < mCtx.leftSub) - fail("Record size is larger than rest of file: " + std::to_string(mCtx.leftRec) + " < " - + std::to_string(mCtx.leftSub)); + // Adjust number of record bytes left; may go negative mCtx.leftRec -= mCtx.leftSub; } @@ -353,6 +350,13 @@ namespace ESM { if (!hasMoreRecs()) fail("No more records, getRecName() failed"); + if (hasMoreSubs()) + fail("Previous record contains unread bytes"); + + // We went out of the previous record's bounds. Backtrack. + if (mCtx.leftRec < 0) + mEsm->seekg(mCtx.leftRec, std::ios::cur); + getName(mCtx.recName); mCtx.leftFile -= decltype(mCtx.recName)::sCapacity; @@ -373,11 +377,8 @@ namespace ESM void ESMReader::getRecHeader(uint32_t& flags) { - // General error checking if (mCtx.leftFile < static_cast(3 * sizeof(uint32_t))) fail("End of file while reading record header"); - if (mCtx.leftRec) - fail("Previous record contains unread bytes"); std::uint32_t leftRec = 0; getUint(leftRec);