Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions core/libs/prx/libc/include/FilesystemError.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ inline bool HasNonDirectoryPrefix_nid_no_patch(const std::filesystem::path& nati
return false;
}

inline bool NamesNonDirectoryWithSlash_nid_no_patch(const std::filesystem::path& native) {
if (native.has_filename()) return false;
auto named = native;
while (!named.has_filename() && named.has_relative_path()) named = named.parent_path();
std::error_code error;
const auto status = std::filesystem::status(named, error);
return std::filesystem::exists(status) && !std::filesystem::is_directory(status);
}

inline int NotFoundError_nid_no_patch(const std::filesystem::path& native) {
return HasNonDirectoryPrefix_nid_no_patch(native) ? 20 : 2;
}
Expand Down
1 change: 1 addition & 0 deletions core/libs/prx/libc/src/Filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ extern "C" int APS5_VABI remove_nid_postfix(const char* path) {
errno = 22;
return -1;
}
if (NamesNonDirectoryWithSlash_nid_no_patch(resolved)) { errno = 20; return -1; }
std::error_code error;
#ifdef _WIN32
const DWORD attributes = GetFileAttributesW(resolved.c_str());
Expand Down
2 changes: 0 additions & 2 deletions core/libs/prx/libc/src/General.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,11 @@ std::optional<std::filesystem::path> ResolveAlias(const std::string& guestPath,
const auto result = std::filesystem::path(host).make_preferred();
return module ? PathOrRelinkedModule(result) : result;
}
#ifndef _WIN32
if (guestPath.back() == '/') {
auto result = ResolveHostPath(host, SplitNames(std::string_view(relative).substr(prefix.size() + 1)));
result /= "";
return module ? PathOrRelinkedModule(result) : result;
}
#endif
return ResolveHostPath(host, SplitNames(std::string_view(relative).substr(prefix.size() + 1)), module).make_preferred();
}
return std::nullopt;
Expand Down
1 change: 1 addition & 0 deletions core/libs/prx/libc/src/Rename.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ extern "C" int RenameGuestPath_nid_no_patch(const char* from, const char* to) {
return -1;
}
const auto destination = ResolvePath_nid_no_patch(to);
if (NamesNonDirectoryWithSlash_nid_no_patch(source) || (std::filesystem::exists(source) && NamesNonDirectoryWithSlash_nid_no_patch(destination))) { errno = 20; return -1; }
int error = RenamePath_nid_no_patch(source, destination);
if (error == 2) {
std::error_code status;
Expand Down
2 changes: 2 additions & 0 deletions core/libs/prx/libkernel/File/src/Open.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode) {
APS5_LOG_ERR("open failed path=%s resolveError=%d result=0x%08X", path != nullptr ? path : "<null>", error, static_cast<unsigned>(result));
return result;
}
if (NamesNonDirectoryWithSlash_nid_no_patch(native)) return SceErrorFromErrno(ENOTDIR);
const int result = OpenNative(native, flags, mode);
if (result < 0) {
const auto resolved = native.u8string();
Expand Down Expand Up @@ -416,6 +417,7 @@ int APS5_VABI sceKernelUnlink(const char* path) {
std::filesystem::path native;
if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error);
constexpr int GuestEperm = 1;
if (NamesNonDirectoryWithSlash_nid_no_patch(native)) return SceErrorFromErrno(20);
std::error_code error;
if (std::filesystem::is_directory(std::filesystem::symlink_status(native, error))) return SceErrorFromErrno(GuestEperm);
if (NativeUnlink(native) != 0) {
Expand Down
2 changes: 0 additions & 2 deletions core/libs/tests/GuestFilesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ static void TestParentTraversal() {
checkInvalid("/parent-test-mount/present.txt/..", 20);
FileStat status{};
Require(sceKernelStat("/parent-test-mount/existing/../present.txt", &status) == 0 && status.st_size == 9);
#ifndef _WIN32
for (const char* name : {"slash-unlink", "slash-remove", "slash-rename", "slash-open", "slash-kernel"}) std::ofstream(root / name) << "kept";
Require(unlink_nid_postfix("/parent-test-mount/slash-unlink/") == -1 && *__error_nid_postfix() == 20);
Require(remove_nid_postfix("/parent-test-mount/slash-remove/") == -1 && *__error_nid_postfix() == 20);
Expand All @@ -250,7 +249,6 @@ static void TestParentTraversal() {
Require(sceKernelStat("/parent-test-mount/Existing/", &status) == 0 && (status.st_mode & 0170000) == 0040000);
Require(mkdir_nid_postfix("/parent-test-mount/slash-directory/", 0755) == 0 && std::filesystem::is_directory(root / "slash-directory"));
Require(rmdir_nid_postfix("/parent-test-mount/slash-directory/") == 0 && !std::filesystem::exists(root / "slash-directory"));
#endif
RemovePathAlias_nid_no_patch("parent-test-mount");
std::error_code linkError;
std::filesystem::create_directory_symlink("Existing", root / "directory-link", linkError);
Expand Down
Loading