Fixup VFS error checking

Many users of VFS didn't check for nullptr or 0 results leading to
various potential issues, to mitigate this introduce error checking to
VFS by default. The original variants can still be used through the
*Unchecked family of functions.
This commit is contained in:
Billy Laws 2021-03-05 15:20:26 +00:00 committed by ◱ Mark
parent 87ac25c1a1
commit 6390561f0f
8 changed files with 61 additions and 16 deletions

View File

@ -16,10 +16,11 @@ namespace skyline::loader {
if (exeFs == nullptr)
throw exception("Cannot load a null ExeFS");
auto nsoFile{exeFs->OpenFile("rtld")};
if (nsoFile == nullptr)
if (!exeFs->FileExists("rtld"))
throw exception("Cannot load an ExeFS that doesn't contain rtld");
auto nsoFile{exeFs->OpenFile("rtld")};
state.process->memory.InitializeVmm(process->npdm.meta.flags.type);
auto loadInfo{NsoLoader::LoadNso(loader, nsoFile, process, state, 0, "rtld.nso")};

View File

@ -50,7 +50,7 @@ namespace skyline::loader {
// Use the first icon file available
for (const auto &entry : root->Read()) {
if (entry.name.rfind("icon") == 0) {
icon = controlRomFs->OpenFile(entry.name);
icon = controlRomFs->OpenFileUnchecked(entry.name);
break;
}
}

View File

@ -23,7 +23,7 @@ namespace skyline::service::fssrv {
return result::InvalidSize;
}
response.Push<u32>(static_cast<u32>(backing->Read(request.outputBuf.at(0), offset)));
response.Push<u32>(static_cast<u32>(backing->ReadUnchecked(request.outputBuf.at(0), offset)));
return {};
}

View File

@ -38,7 +38,7 @@ namespace skyline::service::fssrv {
if (!backing->FileExists(path))
return result::PathDoesNotExist;
auto file{backing->OpenFile(path, mode)};
auto file{backing->OpenFileUnchecked(path, mode)};
if (file == nullptr)
return result::UnexpectedFailure;
else

View File

@ -53,14 +53,30 @@ namespace skyline::vfs {
* @param offset The offset to start reading from
* @return The amount of bytes read
*/
size_t Read(span <u8> output, size_t offset = 0) {
size_t ReadUnchecked(span <u8> output, size_t offset = 0) {
if (!mode.read)
throw exception("Attempting to read a backing that is not readable");
if ((static_cast<ssize_t>(size) - offset) < output.size())
return ReadImpl(output, offset);
};
/**
* @brief Read bytes from the backing at a particular offset to a buffer and check to ensure the full size was read
* @param output The object to write the data read to
* @param offset The offset to start reading from
* @return The amount of bytes read
*/
size_t Read(span <u8> output, size_t offset = 0) {
if (offset > size)
throw exception("Offset cannot be past the end of a backing");
if ((size - offset) < output.size())
throw exception("Trying to read past the end of a backing: 0x{:X}/0x{:X} (Offset: 0x{:X})", output.size(), size, offset);
return ReadImpl(output, offset);
if (ReadUnchecked(output, offset) != size)
throw exception("Failed to read the requested size from backing");
return size;
};
/**

View File

@ -25,7 +25,7 @@ namespace skyline::vfs {
size_t sectorOffset{offset % SectorSize};
if (sectorOffset == 0) {
size_t read{backing->Read(output, offset)};
size_t read{backing->ReadUnchecked(output, offset)};
if (read != size)
return 0;
{
@ -38,7 +38,7 @@ namespace skyline::vfs {
size_t sectorStart{offset - sectorOffset};
std::vector<u8> blockBuf(SectorSize);
size_t read{backing->Read(blockBuf, sectorStart)};
size_t read{backing->ReadUnchecked(blockBuf, sectorStart)};
if (read != SectorSize)
return 0;
{
@ -53,6 +53,6 @@ namespace skyline::vfs {
size_t readInBlock{SectorSize - sectorOffset};
std::memcpy(output.data(), blockBuf.data() + sectorOffset, readInBlock);
return readInBlock + Read(output.subspan(readInBlock), offset + readInBlock);
return readInBlock + ReadUnchecked(output.subspan(readInBlock), offset + readInBlock);
}
}

View File

@ -62,15 +62,29 @@ namespace skyline::vfs {
* @brief Opens a file from the specified path in the filesystem
* @param path The path to the file
* @param mode The mode to open the file with
* @return A shared pointer to a Backing object of the file
* @return A shared pointer to a Backing object of the file (may be nullptr)
*/
std::shared_ptr<Backing> OpenFile(const std::string &path, Backing::Mode mode = {true, false, false}) {
std::shared_ptr<Backing> OpenFileUnchecked(const std::string &path, Backing::Mode mode = {true, false, false}) {
if (!mode.write && !mode.read)
throw exception("Cannot open a file with a mode that is neither readable nor writable");
return OpenFileImpl(path, mode);
}
/**
* @brief Opens a file from the specified path in the filesystem and throws an exception if opening fails
* @param path The path to the file
* @param mode The mode to open the file with
* @return A shared pointer to a Backing object of the file
*/
std::shared_ptr<Backing> OpenFile(const std::string &path, Backing::Mode mode = {true, false, false}) {
auto file{OpenFileUnchecked(path, mode)};
if (file == nullptr)
throw exception("Failed to open file: {}", path);
return file;
}
/**
* @brief Queries the type of the entry given by path
* @param path The path to the entry
@ -104,13 +118,27 @@ namespace skyline::vfs {
* @brief Opens a directory from the specified path in the filesystem
* @param path The path to the directory
* @param listMode The list mode for the directory
* @return A shared pointer to a Directory object of the directory
* @return A shared pointer to a Directory object of the directory (may be nullptr)
*/
std::shared_ptr<Directory> OpenDirectory(const std::string &path, Directory::ListMode listMode = {true, true}) {
std::shared_ptr<Directory> OpenDirectoryUnchecked(const std::string &path, Directory::ListMode listMode = {true, true}) {
if (!listMode.raw)
throw exception("Cannot open a directory with an empty listMode");
return OpenDirectoryImpl(path, listMode);
};
/**
* @brief Opens a directory from the specified path in the filesystem and throws an exception if opening fails
* @param path The path to the directory
* @param listMode The list mode for the directory
* @return A shared pointer to a Directory object of the directory
*/
std::shared_ptr<Directory> OpenDirectory(const std::string &path, Directory::ListMode listMode = {true, true}) {
auto dir{OpenDirectoryUnchecked(path, listMode)};
if (dir == nullptr)
throw exception("Failed to open directory: {}", path);
return dir;
};
};
}

View File

@ -16,7 +16,7 @@ namespace skyline::vfs {
protected:
size_t ReadImpl(span <u8> output, size_t offset) override {
return backing->Read(output, baseOffset + offset);
return backing->ReadUnchecked(output, baseOffset + offset);
}
public: