mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-04 23:35:12 +01:00
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:
parent
87ac25c1a1
commit
6390561f0f
@ -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")};
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user