Size of an array is not a valid index.
components/esm4/reader.cpp:925:15: error: Out of bound access to memory after the end of 'sGroupType' [clang-analyzer-security.ArrayBound,-warnings-as-errors]
925 | ss << sGroupType[std::min<std::size_t>(type, std::size(sGroupType))]; // avoid out of range
| ^
components/esm4/reader.cpp:627:13: note: Assuming field 'groupSize' is equal to field 'recHeaderSize'
627 | if (mCtx.recordHeader.group.groupSize == (std::uint32_t)mCtx.recHeaderSize)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:627:9: note: Taking true branch
627 | if (mCtx.recordHeader.group.groupSize == (std::uint32_t)mCtx.recHeaderSize)
| ^
components/esm4/reader.cpp:634:17: note: Assuming the condition is true
634 | if (!mCtx.groupStack.empty()) // top group may be empty (e.g. HAIR in Skyrim)
| ^~~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:634:13: note: Taking true branch
634 | if (!mCtx.groupStack.empty()) // top group may be empty (e.g. HAIR in Skyrim)
| ^
components/esm4/reader.cpp:638:17: note: Calling 'Reader::exitGroupCheck'
638 | exitGroupCheck();
| ^~~~~~~~~~~~~~~~
components/esm4/reader.cpp:650:13: note: Assuming the condition is false
650 | if (mCtx.groupStack.empty())
| ^~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:650:9: note: Taking false branch
650 | if (mCtx.groupStack.empty())
| ^
components/esm4/reader.cpp:655:16: note: Assuming 'lastGroupSize' is <= field 'second'
655 | while (mCtx.groupStack.back().second >= lastGroupSize)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:655:9: note: Loop condition is true. Entering loop body
655 | while (mCtx.groupStack.back().second >= lastGroupSize)
| ^
components/esm4/reader.cpp:663:17: note: Assuming 'overshoot' is <= 0
663 | if (overshoot > 0)
| ^~~~~~~~~~~~~
components/esm4/reader.cpp:663:13: note: Taking false branch
663 | if (overshoot > 0)
| ^
components/esm4/reader.cpp:676:17: note: Assuming the condition is false
676 | if (mCtx.groupStack.empty())
| ^~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:676:13: note: Taking false branch
676 | if (mCtx.groupStack.empty())
| ^
components/esm4/reader.cpp:682:17: note: Assuming 'lastGroupSize' is >= field 'second'
682 | if (lastGroupSize < mCtx.groupStack.back().second)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:682:13: note: Taking false branch
682 | if (lastGroupSize < mCtx.groupStack.back().second)
| ^
components/esm4/reader.cpp:686:17: note: Assuming 'lastGroupSize' is < field 'second'
686 | if (mCtx.groupStack.back().second > lastGroupSize) // FIXME: debugging only
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:686:13: note: Taking true branch
686 | if (mCtx.groupStack.back().second > lastGroupSize) // FIXME: debugging only
| ^
components/esm4/reader.cpp:687:30: note: Calling 'printLabel'
687 | std::cerr << printLabel(mCtx.groupStack.back().first.label, mCtx.groupStack.back().first.type)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
components/esm4/reader.cpp:925:15: note: Access of 'sGroupType' at index 12, while it holds only 12 'class std::basic_string_view<char>' elements
925 | ss << sGroupType[std::min<std::size_t>(type, std::size(sGroupType))]; // avoid out of range
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
But do not initialize. If the meta information is invalid and has a big
value, initialization will take significant amount of time but there
might be no actual data in the file because it's too small.
If there is a failure to read the file like incomplete read, bad returns
false, but fail returns true. This is important for reading number of
items more than the file actually has.
bhkListShape contains a list of subshape references that need to be
resolved after initial parsing. Without calling postRecordList(), the
mSubshapes list would contain unresolved RecordPtrs.
This adds the missing post() override to properly load subshape data,
consistent with other NIF record types that contain RecordPtr lists.
Implement sol_lua_push for ESM::RefId to automatically convert empty
RefIds to nil in Lua. This fixes cell.region and cell.worldSpaceId
returning empty strings, and applies the same pattern consistently
across all Lua bindings.
Removes LuaUtil::serializeRefId as it's no longer needed.
Fixes#8718