Skip to content

Commit

Permalink
Ignore invalid tree entries
Browse files Browse the repository at this point in the history
  • Loading branch information
x1nixmzeng committed Jan 5, 2021
1 parent 70adb6f commit e8c24b7
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 48 deletions.
17 changes: 12 additions & 5 deletions src/vfs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ SetupState Container::setup(const std::wstring &filename) {

if (!vd.validate()) {
// Some "dual layer" ISO files will have both a video and game partition
constexpr static size_t sc_gamePartitionOffset = 2048 * 32 * 6192;
constexpr static size_t sc_gamePartitionOffset =
xdvdfs::SECTOR_SIZE * 32 * 6192;

stream->m_offset = sc_gamePartitionOffset;

Expand Down Expand Up @@ -82,7 +83,6 @@ Container::getFolderList(const std::filesystem::path &path) const {
}

void Container::build(xdvdfs::Stream &file, xdvdfs::FileEntry &dirent) {
// TODO consider std::filesystem::path::preferred_separator
xdvdfs::FileEntry root("\\");
auto newHandle = registerFileEntry(root, sc_invalidHandle);

Expand All @@ -96,17 +96,24 @@ void Container::buildFromTreeRecursive(xdvdfs::Stream &file,

if (dirent.isDirectory()) {
xdvdfs::FileEntry entry = dirent.getFirstEntry(file);
buildFromTreeRecursive(file, entry, newHandle);
if (entry.validate()) {
buildFromTreeRecursive(file, entry, newHandle);
}
}

if (dirent.hasLeftChild()) {
xdvdfs::FileEntry entry = dirent.getLeftChild(file);
buildFromTreeRecursive(file, entry, parent);

if (entry.validate()) {
buildFromTreeRecursive(file, entry, parent);
}
}

if (dirent.hasRightChild()) {
xdvdfs::FileEntry entry = dirent.getRightChild(file);
buildFromTreeRecursive(file, entry, parent);
if (entry.validate()) {
buildFromTreeRecursive(file, entry, parent);
}
}
}

Expand Down
90 changes: 54 additions & 36 deletions src/xdvdfs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,28 @@
#include <vector>

namespace xdvdfs {
bool VolumeDescriptor::validate() {
void VolumeDescriptor::readFromFile(Stream &file) {
std::vector<char> buffer(SECTOR_SIZE);

{
std::lock_guard<std::mutex> lock(file.m_fileMutex);

file.m_file.seekg(VOLUME_DESCRIPTOR_SECTOR * SECTOR_SIZE + file.m_offset,
std::ifstream::beg);
file.m_file.read(buffer.data(), buffer.size());
}

std::copy(buffer.begin(), buffer.begin() + 0x14, m_id1);
std::copy(buffer.begin() + 0x14, buffer.begin() + 0x18,
reinterpret_cast<char *>(&m_rootDirTableSector));
std::copy(buffer.begin() + 0x18, buffer.begin() + 0x1C,
reinterpret_cast<char *>(&m_rootDirTableSize));
std::copy(buffer.begin() + 0x1C, buffer.begin() + 0x24,
reinterpret_cast<char *>(&m_filetime));
std::copy(buffer.begin() + 0x7EC, buffer.end(), m_id2);
}

bool VolumeDescriptor::validate() const {
if (std::memcmp(m_id1, MAGIC_ID, std::size(m_id1)) != 0) {
return false;
}
Expand All @@ -23,48 +44,26 @@ bool VolumeDescriptor::validate() {
return true;
}

FileEntry::FileEntry(const FileEntry &other)
: m_leftSubTree(other.m_leftSubTree), m_rightSubTree(other.m_rightSubTree),
m_startSector(other.m_startSector), m_fileSize(other.m_fileSize),
m_attributes(other.m_attributes), m_filename(other.m_filename),
m_sectorNumber(other.m_sectorNumber) {}

FileEntry::FileEntry(const std::string &name)
: m_leftSubTree(0), m_rightSubTree(0), m_startSector(0), m_fileSize(0),
m_attributes(FileEntry::FILE_DIRECTORY), m_filename(name),
m_sectorNumber(0) {}

FileEntry VolumeDescriptor::getRootDirEntry(Stream &file) {
FileEntry VolumeDescriptor::getRootDirEntry(Stream &file) const {
FileEntry dirent;

dirent.readFromFile(file, m_rootDirTableSector, 0);

return dirent;
}
} // namespace xdvdfs

void VolumeDescriptor::readFromFile(Stream &file) {
std::vector<char> buffer(SECTOR_SIZE);

{
std::lock_guard<std::mutex> lock(file.m_fileMutex);
namespace xdvdfs {

file.m_file.seekg(VOLUME_DESCRIPTOR_SECTOR * SECTOR_SIZE + file.m_offset,
std::ifstream::beg);
file.m_file.read(buffer.data(), buffer.size());
}
FileEntry::FileEntry(const FileEntry &other)
: m_leftSubTree(other.m_leftSubTree), m_rightSubTree(other.m_rightSubTree),
m_startSector(other.m_startSector), m_fileSize(other.m_fileSize),
m_attributes(other.m_attributes), m_filename(other.m_filename),
m_sectorNumber(other.m_sectorNumber) {}

std::copy(buffer.begin(), buffer.begin() + 0x14, m_id1);
std::copy(buffer.begin() + 0x14, buffer.begin() + 0x18,
reinterpret_cast<char *>(&m_rootDirTableSector));
std::copy(buffer.begin() + 0x18, buffer.begin() + 0x1C,
reinterpret_cast<char *>(&m_rootDirTableSize));
std::copy(buffer.begin() + 0x1C, buffer.begin() + 0x24,
reinterpret_cast<char *>(&m_filetime));
std::copy(buffer.begin() + 0x7EC, buffer.end(), m_id2);
}
} // namespace xdvdfs
FileEntry::FileEntry(const std::string &name)
: m_attributes(FileEntry::FILE_DIRECTORY), m_filename(name) {}

namespace xdvdfs {
void FileEntry::readFromFile(Stream &file, std::streampos sector,
std::streamoff offset) {
std::vector<char> buffer(SECTOR_SIZE);
Expand All @@ -77,6 +76,8 @@ void FileEntry::readFromFile(Stream &file, std::streampos sector,
file.m_file.read(buffer.data(), buffer.size());
}

m_sectorNumber = sector;

std::copy(buffer.begin(), buffer.begin() + 0x02,
reinterpret_cast<char *>(&m_leftSubTree));
std::copy(buffer.begin() + 0x02, buffer.begin() + 0x04,
Expand All @@ -88,10 +89,11 @@ void FileEntry::readFromFile(Stream &file, std::streampos sector,
std::copy(buffer.begin() + 0x0C, buffer.begin() + 0x0D,
reinterpret_cast<char *>(&m_attributes));

size_t filenameLength = buffer[0x0D];
m_filename = std::string(&buffer[0x0E], filenameLength);
if (validate()) {
size_t filenameLength{static_cast<uint8_t>(buffer[0x0D])};

m_sectorNumber = sector;
m_filename = std::string(&buffer[0x0E], filenameLength);
}
}

const std::string &FileEntry::getFilename() const { return m_filename; }
Expand Down Expand Up @@ -128,6 +130,22 @@ uint32_t FileEntry::read(Stream &file, void *buffer, uint32_t bufferlength,
return 0;
}

bool FileEntry::validate() const {
if (m_leftSubTree == static_cast<uint16_t>(-1)) {
return false;
}

if (m_rightSubTree == static_cast<uint16_t>(-1)) {
return false;
}

if (m_startSector == static_cast<uint32_t>(-1)) {
return false;
}

return true;
}

bool FileEntry::isDirectory() const {
return ((m_attributes & FileEntry::FILE_DIRECTORY) != 0);
}
Expand Down
18 changes: 11 additions & 7 deletions src/xdvdfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ class FileEntry {
FileEntry(const FileEntry &other);
FileEntry(const std::string &name);

void readFromFile(Stream &file, std::streampos pos, std::streamoff offset);
const std::string &getFilename() const;
uint32_t getFileSize() const;
void readFromFile(Stream &file, std::streampos sector, std::streamoff offset);

// matching dokany api for now
uint32_t read(Stream &file, void *buffer, uint32_t bufferlength,
int64_t offset) const;

bool validate() const;

const std::string &getFilename() const;
uint32_t getFileSize() const;

uint8_t getAttributes() const { return m_attributes; }
bool isDirectory() const;
bool hasLeftChild() const;
Expand All @@ -52,8 +55,8 @@ class FileEntry {
static const uint8_t FILE_NORMAL = 0x80;

private:
uint16_t m_leftSubTree{0};
uint16_t m_rightSubTree{0};
uint16_t m_leftSubTree{static_cast<uint16_t>(-1)};
uint16_t m_rightSubTree{static_cast<uint16_t>(-1)};
uint32_t m_startSector{0};
uint32_t m_fileSize{0};
uint8_t m_attributes{0};
Expand All @@ -66,8 +69,9 @@ class VolumeDescriptor {
public:
void readFromFile(Stream &file);

bool validate();
FileEntry getRootDirEntry(Stream &file);
bool validate() const;

FileEntry getRootDirEntry(Stream &file) const;
uint64_t getCreationTime() const { return m_filetime; }

protected:
Expand Down

0 comments on commit e8c24b7

Please sign in to comment.