NANDImporter: Abort extraction if a NAND FST entry is visited more than once
This commit is contained in:
2 files changed
+17
-5
No files matched your search
@@ -129,7 +129,8 @@ bool NANDImporter::ExtractFiles()
|
|||||||
constexpr u16 CLUSTER_CHAIN_END = 0xFFFB;
|
constexpr u16 CLUSTER_CHAIN_END = 0xFFFB;
|
||||||
m_progress_cur = 0;
|
m_progress_cur = 0;
|
||||||
m_progress_max = std::ranges::count(m_superblock->fat, CLUSTER_CHAIN_END);
|
m_progress_max = std::ranges::count(m_superblock->fat, CLUSTER_CHAIN_END);
|
||||||
return ProcessEntry(0, "");
|
std::bitset<FSTEntryCount> visited;
|
||||||
|
return ProcessEntry(0, "", &visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NANDImporter::GetPath(const NANDFSTEntry& entry, const std::string& parent_path)
|
std::string NANDImporter::GetPath(const NANDFSTEntry& entry, const std::string& parent_path)
|
||||||
@@ -138,7 +139,8 @@ std::string NANDImporter::GetPath(const NANDFSTEntry& entry, const std::string&
|
|||||||
return parent_path + '/' + Common::EscapeFileName(name);
|
return parent_path + '/' + Common::EscapeFileName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NANDImporter::ProcessEntry(u16 entry_number, const std::string& parent_path)
|
bool NANDImporter::ProcessEntry(u16 entry_number, const std::string& parent_path,
|
||||||
|
std::bitset<FSTEntryCount>* visited)
|
||||||
{
|
{
|
||||||
while (entry_number != 0xffff)
|
while (entry_number != 0xffff)
|
||||||
{
|
{
|
||||||
@@ -148,6 +150,13 @@ bool NANDImporter::ProcessEntry(u16 entry_number, const std::string& parent_path
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((*visited)[entry_number])
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(DISCIO, "FST entry number {} visited multiple times", entry_number);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*visited)[entry_number] = true;
|
||||||
const NANDFSTEntry entry = m_superblock->fst[entry_number];
|
const NANDFSTEntry entry = m_superblock->fst[entry_number];
|
||||||
|
|
||||||
const std::string path = entry_number == 0 ? parent_path : GetPath(entry, parent_path);
|
const std::string path = entry_number == 0 ? parent_path : GetPath(entry, parent_path);
|
||||||
@@ -165,7 +174,7 @@ bool NANDImporter::ProcessEntry(u16 entry_number, const std::string& parent_path
|
|||||||
else if (type == Type::Directory)
|
else if (type == Type::Directory)
|
||||||
{
|
{
|
||||||
File::CreateDir(m_nand_root + path);
|
File::CreateDir(m_nand_root + path);
|
||||||
if (!ProcessEntry(entry.sub, path))
|
if (!ProcessEntry(entry.sub, path, visited))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <bitset>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -59,13 +60,14 @@ public:
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(NANDFSTEntry) == 0x20, "Wrong size");
|
static_assert(sizeof(NANDFSTEntry) == 0x20, "Wrong size");
|
||||||
|
|
||||||
|
static constexpr u16 FSTEntryCount = 0x17FF;
|
||||||
struct NANDSuperblock
|
struct NANDSuperblock
|
||||||
{
|
{
|
||||||
std::array<char, 4> magic; // "SFFS"
|
std::array<char, 4> magic; // "SFFS"
|
||||||
Common::BigEndianValue<u32> version;
|
Common::BigEndianValue<u32> version;
|
||||||
Common::BigEndianValue<u32> unknown;
|
Common::BigEndianValue<u32> unknown;
|
||||||
std::array<Common::BigEndianValue<u16>, 0x8000> fat;
|
std::array<Common::BigEndianValue<u16>, 0x8000> fat;
|
||||||
std::array<NANDFSTEntry, 0x17FF> fst;
|
std::array<NANDFSTEntry, FSTEntryCount> fst;
|
||||||
std::array<u8, 0x14> pad;
|
std::array<u8, 0x14> pad;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(NANDSuperblock) == 0x40000, "Wrong size");
|
static_assert(sizeof(NANDSuperblock) == 0x40000, "Wrong size");
|
||||||
@@ -78,7 +80,8 @@ private:
|
|||||||
bool ExtractFiles();
|
bool ExtractFiles();
|
||||||
std::string GetPath(const NANDFSTEntry& entry, const std::string& parent_path);
|
std::string GetPath(const NANDFSTEntry& entry, const std::string& parent_path);
|
||||||
std::string FormatDebugString(const NANDFSTEntry& entry);
|
std::string FormatDebugString(const NANDFSTEntry& entry);
|
||||||
bool ProcessEntry(u16 entry_number, const std::string& parent_path);
|
bool ProcessEntry(u16 entry_number, const std::string& parent_path,
|
||||||
|
std::bitset<FSTEntryCount>* visited);
|
||||||
std::vector<u8> GetEntryData(const NANDFSTEntry& entry) const;
|
std::vector<u8> GetEntryData(const NANDFSTEntry& entry) const;
|
||||||
void ExportKeys();
|
void ExportKeys();
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user