common: fs: Validate paths for path length

This commit is contained in:
Morph
2021-05-10 05:22:20 -04:00
parent 34819b34a4
commit 9f5d5e0ded
5 changed files with 93 additions and 40 deletions

View File

@@ -14,8 +14,8 @@ namespace fs = std::filesystem;
// File Operations
bool NewFile(const fs::path& path, u64 size) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -52,8 +52,8 @@ bool NewFile(const fs::path& path, u64 size) {
}
bool RemoveFile(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -86,8 +86,9 @@ bool RemoveFile(const fs::path& path) {
}
bool RenameFile(const fs::path& old_path, const fs::path& new_path) {
if (old_path.empty() || new_path.empty()) {
LOG_ERROR(Common_Filesystem, "One or both input path(s) is empty, old_path={}, new_path={}",
if (!ValidatePath(old_path) || !ValidatePath(new_path)) {
LOG_ERROR(Common_Filesystem,
"One or both input path(s) is not valid, old_path={}, new_path={}",
PathToUTF8String(old_path), PathToUTF8String(new_path));
return false;
}
@@ -129,8 +130,8 @@ bool RenameFile(const fs::path& old_path, const fs::path& new_path) {
std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, FileType type,
FileShareFlag flag) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return nullptr;
}
@@ -162,8 +163,8 @@ std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, File
// Directory Operations
bool CreateDir(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -196,8 +197,8 @@ bool CreateDir(const fs::path& path) {
}
bool CreateDirs(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -232,8 +233,8 @@ bool CreateParentDirs(const fs::path& path) {
}
bool RemoveDir(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -266,8 +267,8 @@ bool RemoveDir(const fs::path& path) {
}
bool RemoveDirRecursively(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -301,8 +302,8 @@ bool RemoveDirRecursively(const fs::path& path) {
}
bool RemoveDirContentsRecursively(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -353,8 +354,9 @@ bool RemoveDirContentsRecursively(const fs::path& path) {
}
bool RenameDir(const fs::path& old_path, const fs::path& new_path) {
if (old_path.empty() || new_path.empty()) {
LOG_ERROR(Common_Filesystem, "One or both input path(s) is empty, old_path={}, new_path={}",
if (!ValidatePath(old_path) || !ValidatePath(new_path)) {
LOG_ERROR(Common_Filesystem,
"One or both input path(s) is not valid, old_path={}, new_path={}",
PathToUTF8String(old_path), PathToUTF8String(new_path));
return false;
}
@@ -396,8 +398,8 @@ bool RenameDir(const fs::path& old_path, const fs::path& new_path) {
void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable& callback,
DirEntryFilter filter) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return;
}
@@ -452,8 +454,8 @@ void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable
void IterateDirEntriesRecursively(const std::filesystem::path& path,
const DirEntryCallable& callback, DirEntryFilter filter) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return;
}

View File

@@ -20,7 +20,7 @@ class IOFile;
* Creates a new file at path with the specified size.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - The input path's parent directory does not exist
* - Filesystem object at path exists
* - Filesystem at path is read only
@@ -47,7 +47,7 @@ template <typename Path>
* Removes a file at path.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a file
* - Filesystem at path is read only
*
@@ -72,7 +72,7 @@ template <typename Path>
* Renames a file from old_path to new_path.
*
* Failures occur when:
* - One or both input path(s) is empty
* - One or both input path(s) is not valid
* - Filesystem object at old_path does not exist
* - Filesystem object at old_path is not a file
* - Filesystem object at new_path exists
@@ -109,7 +109,7 @@ template <typename Path1, typename Path2>
* These behaviors are documented in each enum value of FileAccessMode.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a file
* - The file is not opened
*
@@ -147,7 +147,7 @@ template <typename Path>
* If you intend to create the parent directory of a file, use CreateParentDir instead.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - The input path's parent directory does not exist
* - Filesystem at path is read only
*
@@ -176,7 +176,7 @@ template <typename Path>
* Unlike CreateDir, this creates all of input path's parent directories if they do not exist.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem at path is read only
*
* @param path Filesystem path
@@ -242,7 +242,7 @@ template <typename Path>
* Removes a directory at path.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a directory
* - The given directory is not empty
* - Filesystem at path is read only
@@ -268,7 +268,7 @@ template <typename Path>
* Removes all the contents within the given directory and removes the directory itself.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a directory
* - Filesystem at path is read only
*
@@ -293,7 +293,7 @@ template <typename Path>
* Removes all the contents within the given directory without removing the directory itself.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a directory
* - Filesystem at path is read only
*
@@ -318,7 +318,7 @@ template <typename Path>
* Renames a directory from old_path to new_path.
*
* Failures occur when:
* - One or both input path(s) is empty
* - One or both input path(s) is not valid
* - Filesystem object at old_path does not exist
* - Filesystem object at old_path is not a directory
* - Filesystem object at new_path exists
@@ -358,7 +358,7 @@ template <typename Path1, typename Path2>
* If the callback returns false or there is an error, the iteration is immediately halted.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a directory
*
* @param path Filesystem path
@@ -388,7 +388,7 @@ void IterateDirEntries(const Path& path, const DirEntryCallable& callback,
* If the callback returns false or there is an error, the iteration is immediately halted.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path does not exist
* - Filesystem object at path is not a directory
*

View File

@@ -4,10 +4,6 @@
#pragma once
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
// yuzu data directories
#define YUZU_DIR "yuzu"

View File

@@ -37,6 +37,16 @@
#endif
#endif
#ifndef MAX_PATH
#ifdef _WIN32
// This is the maximum number of UTF-16 code units permissible in Windows file paths
#define MAX_PATH 260
#else
// This is the maximum number of UTF-8 code units permissible in all other OSes' file paths
#define MAX_PATH 1024
#endif
#endif
namespace Common::FS {
namespace fs = std::filesystem;
@@ -125,6 +135,27 @@ std::string PathToUTF8String(const fs::path& path) {
return std::string{utf8_string.begin(), utf8_string.end()};
}
bool ValidatePath(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
return false;
}
#ifdef _WIN32
if (path.u16string().size() >= MAX_PATH) {
LOG_ERROR(Common_Filesystem, "Input path is too long, path={}", PathToUTF8String(path));
return false;
}
#else
if (path.u8string().size() >= MAX_PATH) {
LOG_ERROR(Common_Filesystem, "Input path is too long, path={}", PathToUTF8String(path));
return false;
}
#endif
return true;
}
fs::path ConcatPath(const fs::path& first, const fs::path& second) {
const bool second_has_dir_sep = IsDirSeparator(second.u8string().front());

View File

@@ -34,6 +34,30 @@ enum class YuzuPath {
*/
[[nodiscard]] std::string PathToUTF8String(const std::filesystem::path& path);
/**
* Validates a given path.
*
* A given path is valid if it meets these conditions:
* - The path is not empty
* - The path is not too long
*
* @param path Filesystem path
*
* @returns True if the path is valid, false otherwise.
*/
[[nodiscard]] bool ValidatePath(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] bool ValidatePath(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return ValidatePath(ToU8String(path));
} else {
return ValidatePath(std::filesystem::path{path});
}
}
#endif
/**
* Concatenates two filesystem paths together.
*