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
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Remove debug-related includes
- Add some trivial missing includes
- Remove useless {}
- Move the known-but-skipped-records are the end of the switch-cases
- Always throw on unknown records
Size of the files is in order of megabytes at max. Storing offset lookup table
to read from file on demand is less efficient than reading from memory for such
size.
Read and store offsets first. Sort them to read values sequentially. Memoize
last offset and value to avoid reading the same value twice. Use seek only when
current possition does not match offset. Optimize seek for short distance by
calling read instead.
toUtf8 returns a string view to the input when input string is ASCII and nothing
is written to the buffer which means output string of Reader::getStringImpl is
not modified.
Move input to the output string and resize it in this case.
This class does not serve any useful purpose now. It was added as a first step
in attempt to define common interface for ESM3 and ESM4 readers. But this is not
going to happen.