Skip to content

Commit c06f94f

Browse files
committed
Merge branch 'fix_esmtool_afl_findings' into 'master'
Check index for ESM4 race parts See merge request OpenMW/openmw!4987
2 parents dcedbfd + c7830d9 commit c06f94f

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

components/esm4/loadrace.cpp

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,23 @@
2727
#include "loadrace.hpp"
2828

2929
#include <cstring>
30+
#include <format>
31+
#include <optional>
3032
#include <stdexcept>
3133

3234
#include "reader.hpp"
3335
//#include "writer.hpp"
3436

37+
namespace
38+
{
39+
decltype(auto) at(auto& values, std::uint32_t index, std::string_view name, ESM4::Reader& reader)
40+
{
41+
if (index >= values.size())
42+
reader.fail(std::format("{} index is out of range: {} >= {}", name, index, values.size()));
43+
return values[index];
44+
}
45+
}
46+
3547
void ESM4::Race::load(ESM4::Reader& reader)
3648
{
3749
mId = reader.getFormIdFromHeader();
@@ -44,7 +56,7 @@ void ESM4::Race::load(ESM4::Reader& reader)
4456

4557
bool isMale = false;
4658
int currPart = -1; // 0 = head, 1 = body, 2 = egt, 3 = hkx
47-
std::uint32_t currentIndex = 0xffffffff;
59+
std::optional<std::uint32_t> currentIndex;
4860

4961
while (reader.getSubRecordHeader())
5062
{
@@ -293,12 +305,14 @@ void ESM4::Race::load(ESM4::Reader& reader)
293305
mHeadPartIdsFemale.resize(5);
294306
}
295307

296-
currentIndex = 0xffffffff;
308+
currentIndex.reset();
297309
break;
298310
}
299311
case ESM::fourCC("INDX"):
300312
{
301-
reader.get(currentIndex);
313+
std::uint32_t value = 0;
314+
reader.get(value);
315+
currentIndex = value;
302316
// FIXME: below check is rather useless
303317
// if (headpart)
304318
//{
@@ -315,25 +329,26 @@ void ESM4::Race::load(ESM4::Reader& reader)
315329
}
316330
case ESM::fourCC("MODL"):
317331
{
318-
if (currentIndex == 0xffffffff)
332+
if (!currentIndex.has_value())
319333
{
320334
reader.skipSubRecordData();
321335
}
322336
else if (currPart == 0) // head part
323337
{
324338
if (isMale || isTES4)
325-
reader.getZString(mHeadParts[currentIndex].mesh);
339+
reader.getZString(at(mHeadParts, *currentIndex, "head parts", reader).mesh);
326340
else
327-
reader.getZString(mHeadPartsFemale[currentIndex].mesh); // TODO: check TES4
341+
// TODO: check TES4
342+
reader.getZString(at(mHeadPartsFemale, *currentIndex, "head parts female", reader).mesh);
328343

329344
// TES5 keeps head part formid in mHeadPartIdsMale and mHeadPartIdsFemale
330345
}
331346
else if (currPart == 1) // body part
332347
{
333348
if (isMale)
334-
reader.getZString(mBodyPartsMale[currentIndex].mesh);
349+
reader.getZString(at(mBodyPartsMale, *currentIndex, "body parts male", reader).mesh);
335350
else
336-
reader.getZString(mBodyPartsFemale[currentIndex].mesh);
351+
reader.getZString(at(mBodyPartsFemale, *currentIndex, "body parts female", reader).mesh);
337352

338353
// TES5 seems to have no body parts at all, instead keep EGT models
339354
}
@@ -355,23 +370,24 @@ void ESM4::Race::load(ESM4::Reader& reader)
355370
break; // always 0x0000?
356371
case ESM::fourCC("ICON"):
357372
{
358-
if (currentIndex == 0xffffffff)
373+
if (!currentIndex.has_value())
359374
{
360375
reader.skipSubRecordData();
361376
}
362377
else if (currPart == 0) // head part
363378
{
364379
if (isMale || isTES4)
365-
reader.getZString(mHeadParts[currentIndex].texture);
380+
reader.getZString(at(mHeadParts, *currentIndex, "head parts", reader).texture);
366381
else
367-
reader.getZString(mHeadPartsFemale[currentIndex].texture); // TODO: check TES4
382+
// TODO: check TES4
383+
reader.getZString(at(mHeadPartsFemale, *currentIndex, "head parts female", reader).texture);
368384
}
369385
else if (currPart == 1) // body part
370386
{
371387
if (isMale)
372-
reader.getZString(mBodyPartsMale[currentIndex].texture);
388+
reader.getZString(at(mBodyPartsMale, *currentIndex, "body parts male", reader).texture);
373389
else
374-
reader.getZString(mBodyPartsFemale[currentIndex].texture);
390+
reader.getZString(at(mBodyPartsFemale, *currentIndex, "body parts female", reader).texture);
375391
}
376392
else
377393
reader.skipSubRecordData(); // FIXME TES5
@@ -402,7 +418,7 @@ void ESM4::Race::load(ESM4::Reader& reader)
402418
if (isTES4)
403419
currentIndex = 4; // FIXME: argonian tail mesh without preceeding INDX
404420
else
405-
currentIndex = 0xffffffff;
421+
currentIndex.reset();
406422

407423
break;
408424
}
@@ -589,20 +605,20 @@ void ESM4::Race::load(ESM4::Reader& reader)
589605
ESM::FormId formId;
590606
reader.getFormId(formId);
591607

592-
if (currentIndex != 0xffffffff)
608+
if (currentIndex.has_value())
593609
{
594610
// FIXME: no order? head, mouth, eyes, brow, hair
595611
if (isMale)
596612
{
597613
if (currentIndex >= mHeadPartIdsMale.size())
598-
mHeadPartIdsMale.resize(currentIndex + 1);
599-
mHeadPartIdsMale[currentIndex] = formId;
614+
mHeadPartIdsMale.resize(*currentIndex + 1);
615+
mHeadPartIdsMale[*currentIndex] = formId;
600616
}
601617
else
602618
{
603619
if (currentIndex >= mHeadPartIdsFemale.size())
604-
mHeadPartIdsFemale.resize(currentIndex + 1);
605-
mHeadPartIdsFemale[currentIndex] = formId;
620+
mHeadPartIdsFemale.resize(*currentIndex + 1);
621+
mHeadPartIdsFemale[*currentIndex] = formId;
606622
}
607623
}
608624

0 commit comments

Comments
 (0)