Skip to content

Commit 532342f

Browse files
committed
ZoneFile bugfix + hash_table access
- Fixed start* in ZoneFile::Read pointing to the original buffer. This could result in members pointing to the old buffer instead of the zone files own copy of the buffer. This could cause a use after free or other memory erros if pointer members were accessed after the original buffer was freed. - Added access to the relation data hashtable. Still pretty sure the game doesn't use it for anything. Gonna add generation of export with Nanoforge soon just in case. Seems simple enough to generate.
1 parent e6ff11d commit 532342f

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

RfgTools++/RfgTools++/formats/zones/ZoneFile.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@ std::optional<ZoneFile> ZoneFile::Read(const std::string& path)
2121
std::optional<ZoneFile> ZoneFile::Read(std::span<u8> bytes, const std::string& name)
2222
{
2323
size_t sizeBytes = bytes.size_bytes();
24-
u8* start = bytes.data();
25-
u8* end = start + sizeBytes;
2624

27-
//Take ownership of buffer
25+
//Copy bytes to internal buffer
2826
ZoneFile zoneFile;
2927
zoneFile.Name = name;
3028
zoneFile._data = std::make_unique<u8[]>(sizeBytes);
31-
memcpy(zoneFile._data.get(), start, sizeBytes);
29+
memcpy(zoneFile._data.get(), bytes.data(), sizeBytes);
30+
31+
//Get start and end position of data
32+
u8* start = zoneFile._data.get();
33+
u8* end = start + sizeBytes;
3234

3335
//Read header
3436
memcpy(&zoneFile.Header, start, sizeof(ZoneFileHeader));
@@ -38,7 +40,7 @@ std::optional<ZoneFile> ZoneFile::Read(std::span<u8> bytes, const std::string& n
3840
zoneFile.HasRelationData = (zoneFile.Header.DistrictFlags & 5) == 0;
3941
if (zoneFile.HasRelationData)
4042
{
41-
zoneFile.RelationData = pos;
43+
zoneFile.RelationData = (ZoneFileRelationData*)pos;
4244
pos += 87368;
4345
}
4446
if (zoneFile.Empty())

RfgTools++/RfgTools++/formats/zones/ZoneFile.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,25 @@ class ZoneFileHeader
1919
};
2020
static_assert(sizeof(ZoneFileHeader) == 24, "sizeof(ZoneFileHeader) must be 24 to match RFG zone file format.");
2121

22+
struct ZoneFileRelationData
23+
{
24+
u8 Padding0[4];
25+
u16 Free;
26+
u16 Slot[7280];
27+
u16 Next[7280];
28+
u8 Padding1[2];
29+
u32 Keys[7280];
30+
u32 Values[7280];
31+
};
32+
static_assert(sizeof(ZoneFileRelationData) == 87368);
33+
2234
//Zone format version 36. Found in rfgzone_pc and layer_pc files in RFG and RFGR.
2335
class ZoneFile
2436
{
2537
public:
2638
ZoneFileHeader Header;
2739
bool HasRelationData = false;
28-
u8* RelationData = nullptr;
40+
ZoneFileRelationData* RelationData = nullptr;
2941
//Start of the zone object list. You must use NextObject() for iteration since there's variable size property blocks between objects.
3042
ZoneObject* Objects = nullptr;
3143
u32 ObjectsSize = 0;

0 commit comments

Comments
 (0)