mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 13:01:50 +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)
|
if (exeFs == nullptr)
|
||||||
throw exception("Cannot load a null ExeFS");
|
throw exception("Cannot load a null ExeFS");
|
||||||
|
|
||||||
auto nsoFile{exeFs->OpenFile("rtld")};
|
if (!exeFs->FileExists("rtld"))
|
||||||
if (nsoFile == nullptr)
|
|
||||||
throw exception("Cannot load an ExeFS that doesn't contain 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);
|
state.process->memory.InitializeVmm(process->npdm.meta.flags.type);
|
||||||
|
|
||||||
auto loadInfo{NsoLoader::LoadNso(loader, nsoFile, process, state, 0, "rtld.nso")};
|
auto loadInfo{NsoLoader::LoadNso(loader, nsoFile, process, state, 0, "rtld.nso")};
|
||||||
|
@ -50,7 +50,7 @@ namespace skyline::loader {
|
|||||||
// Use the first icon file available
|
// Use the first icon file available
|
||||||
for (const auto &entry : root->Read()) {
|
for (const auto &entry : root->Read()) {
|
||||||
if (entry.name.rfind("icon") == 0) {
|
if (entry.name.rfind("icon") == 0) {
|
||||||
icon = controlRomFs->OpenFile(entry.name);
|
icon = controlRomFs->OpenFileUnchecked(entry.name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace skyline::service::fssrv {
|
|||||||
return result::InvalidSize;
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace skyline::service::fssrv {
|
|||||||
if (!backing->FileExists(path))
|
if (!backing->FileExists(path))
|
||||||
return result::PathDoesNotExist;
|
return result::PathDoesNotExist;
|
||||||
|
|
||||||
auto file{backing->OpenFile(path, mode)};
|
auto file{backing->OpenFileUnchecked(path, mode)};
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
return result::UnexpectedFailure;
|
return result::UnexpectedFailure;
|
||||||
else
|
else
|
||||||
|
@ -53,14 +53,30 @@ namespace skyline::vfs {
|
|||||||
* @param offset The offset to start reading from
|
* @param offset The offset to start reading from
|
||||||
* @return The amount of bytes read
|
* @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)
|
if (!mode.read)
|
||||||
throw exception("Attempting to read a backing that is not readable");
|
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);
|
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};
|
size_t sectorOffset{offset % SectorSize};
|
||||||
if (sectorOffset == 0) {
|
if (sectorOffset == 0) {
|
||||||
size_t read{backing->Read(output, offset)};
|
size_t read{backing->ReadUnchecked(output, offset)};
|
||||||
if (read != size)
|
if (read != size)
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
@ -38,7 +38,7 @@ namespace skyline::vfs {
|
|||||||
|
|
||||||
size_t sectorStart{offset - sectorOffset};
|
size_t sectorStart{offset - sectorOffset};
|
||||||
std::vector<u8> blockBuf(SectorSize);
|
std::vector<u8> blockBuf(SectorSize);
|
||||||
size_t read{backing->Read(blockBuf, sectorStart)};
|
size_t read{backing->ReadUnchecked(blockBuf, sectorStart)};
|
||||||
if (read != SectorSize)
|
if (read != SectorSize)
|
||||||
return 0;
|
return 0;
|
||||||
{
|
{
|
||||||
@ -53,6 +53,6 @@ namespace skyline::vfs {
|
|||||||
|
|
||||||
size_t readInBlock{SectorSize - sectorOffset};
|
size_t readInBlock{SectorSize - sectorOffset};
|
||||||
std::memcpy(output.data(), blockBuf.data() + sectorOffset, readInBlock);
|
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
|
* @brief Opens a file from the specified path in the filesystem
|
||||||
* @param path The path to the file
|
* @param path The path to the file
|
||||||
* @param mode The mode to open the file with
|
* @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)
|
if (!mode.write && !mode.read)
|
||||||
throw exception("Cannot open a file with a mode that is neither readable nor writable");
|
throw exception("Cannot open a file with a mode that is neither readable nor writable");
|
||||||
|
|
||||||
return OpenFileImpl(path, mode);
|
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
|
* @brief Queries the type of the entry given by path
|
||||||
* @param path The path to the entry
|
* @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
|
* @brief Opens a directory from the specified path in the filesystem
|
||||||
* @param path The path to the directory
|
* @param path The path to the directory
|
||||||
* @param listMode The list mode for 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)
|
if (!listMode.raw)
|
||||||
throw exception("Cannot open a directory with an empty listMode");
|
throw exception("Cannot open a directory with an empty listMode");
|
||||||
|
|
||||||
return OpenDirectoryImpl(path, 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:
|
protected:
|
||||||
size_t ReadImpl(span <u8> output, size_t offset) override {
|
size_t ReadImpl(span <u8> output, size_t offset) override {
|
||||||
return backing->Read(output, baseOffset + offset);
|
return backing->ReadUnchecked(output, baseOffset + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user