fix(libkernel): reject empty filesystem paths

This commit is contained in:
MarcZX100 2026-10-11 11:00:35 +00:00
parent 0f863c1022
commit d26c9bcabc
3 changed files with 27 additions and 0 deletions

View File

@ -226,6 +226,7 @@ int APS5_VABI sceKernelStat(const char* path, FileStat* sb) {
if (sb == nullptr) {
throw std::invalid_argument(std::string(__func__) + ": sb is null");
}
if (*path == '\0') return SceErrorFromErrno(2);
std::filesystem::path native;
try {
native = ResolvePath_nid_no_patch(path);
@ -249,6 +250,7 @@ int APS5_VABI sceKernelUnlink(const char* path) {
if (path == nullptr) {
throw std::invalid_argument(std::string(__func__) + ": path is null");
}
if (*path == '\0') return SceErrorFromErrno(2);
auto native = ResolvePath_nid_no_patch(path);
constexpr int GuestEperm = 1;
std::error_code error;

View File

@ -696,6 +696,7 @@ int APS5_VABI unlink_nid_postfix(const char* path) {
int APS5_VABI sceKernelCheckReachability(const char* path) {
if (path == nullptr) return SCE_KERNEL_ERROR_EINVAL;
if (*path == '\0') return SCE_KERNEL_ERROR_ENOENT;
if (std::strlen(path) > 255) return SCE_KERNEL_ERROR_ENAMETOOLONG;
std::error_code error;
return std::filesystem::exists(ResolvePath_nid_no_patch(path), error) ? 0 : SCE_KERNEL_ERROR_ENOENT;
@ -999,6 +1000,7 @@ int64_t APS5_VABI pwritev_nid_postfix(int d, const KernelIovec* iov, int iovcnt,
int APS5_VABI sceKernelRename(const char* from, const char* to) {
if (from == nullptr || to == nullptr) throw std::invalid_argument("sceKernelRename: path is null");
if (*from == '\0' || *to == '\0') return SceErrorFromErrno(GUEST_ENOENT);
const auto source = ResolvePath_nid_no_patch(from);
std::error_code error;
if (!std::filesystem::exists(source, error)) return SceErrorFromErrno(GUEST_ENOENT);
@ -1012,6 +1014,7 @@ int APS5_VABI sceKernelRename(const char* from, const char* to) {
int APS5_VABI sceKernelRmdir(const char* path) {
if (path == nullptr) throw std::invalid_argument("sceKernelRmdir: path is null");
if (*path == '\0') return SceErrorFromErrno(GUEST_ENOENT);
const auto native = ResolvePath_nid_no_patch(path);
std::error_code error;
if (!std::filesystem::is_directory(native, error)) {
@ -1035,6 +1038,7 @@ extern "C" {
int APS5_VABI sceKernelChmod_nid_postfix(const char* path, std::uint16_t mode) {
if (!path) return SceErrorFromErrno(GUEST_EFAULT);
if (!*path) return SceErrorFromErrno(GUEST_ENOENT);
const auto native = ResolvePath_nid_no_patch(path);
if (NativeChmod(native, mode & 07777) != 0) return SceErrorFromErrno(errno);
return 0;
@ -1052,6 +1056,7 @@ int APS5_VABI fchmod_nid_postfix(int d, int mode) {
int APS5_VABI sceKernelTruncate_nid_postfix(const char* path, std::int64_t length) {
if (path == nullptr) throw std::invalid_argument("sceKernelTruncate: path is null");
if (*path == '\0') return SceErrorFromErrno(GUEST_ENOENT);
if (length < 0) return SceErrorFromErrno(GUEST_EINVAL);
const auto native = ResolvePath_nid_no_patch(path);
std::error_code error;
@ -1070,6 +1075,7 @@ int APS5_VABI truncate_nid_postfix(const char* path, std::int64_t length) {
int APS5_VABI sceKernelUtimes_nid_postfix(const char* path, const KernelTimeval* times) {
if (path == nullptr) throw std::invalid_argument("sceKernelUtimes: path is null");
if (*path == '\0') return SceErrorFromErrno(GUEST_ENOENT);
if (times != nullptr) {
for (int i = 0; i < 2; ++i) {
if (times[i].tv_usec < 0 || times[i].tv_usec >= 1000000) return SCE_KERNEL_ERROR_EINVAL;

View File

@ -45,8 +45,10 @@ int APS5_VABI mkdir_nid_postfix(const char*, unsigned short);
int APS5_VABI sceKernelOpen(const char*, int, unsigned short);
int APS5_VABI sceKernelClose(int);
int APS5_VABI sceKernelStat(const char*, FileStat*);
int APS5_VABI sceKernelCheckReachability(const char*);
int APS5_VABI sceKernelFstat(int, FileStat*);
int APS5_VABI sceKernelUnlink(const char*);
int APS5_VABI sceKernelRename(const char*, const char*);
int APS5_VABI sceKernelRmdir(const char*);
int APS5_VABI sceKernelMkdir(const char*, unsigned short);
int* APS5_VABI __error_nid_postfix();
@ -77,6 +79,7 @@ static void Check(bool value, int line) {
int main() {
Require(chmod_nid_postfix(nullptr, 0600) == -1 && *__error_nid_postfix() == 14);
Require(sceKernelChmod_nid_postfix(nullptr, 0600) == static_cast<int>(0x8002000eu));
Require(chmod_nid_postfix("", 0600) == -1 && *__error_nid_postfix() == 2);
Require(chmod_nid_postfix("anyps5_missing_chmod_path", 0600) == -1 && *__error_nid_postfix() == 2);
Require(sceKernelChmod_nid_postfix("anyps5_missing_chmod_path", 0600) == static_cast<int>(0x80020002u));
Require(sceKernelDebugOutText(-1, "text") == static_cast<int>(0x80020016u));
@ -267,6 +270,21 @@ int main() {
const auto rootName = root.string();
{ std::ofstream stream(present); stream << "posix"; }
FileStat status{};
Require(sceKernelStat("", &status) == static_cast<int>(0x80020002u));
Require(sceKernelCheckReachability("") == static_cast<int>(0x80020002u));
Require(sceKernelRename("", presentName.c_str()) == static_cast<int>(0x80020002u));
Require(sceKernelRename(presentName.c_str(), "") == static_cast<int>(0x80020002u));
Require(sceKernelRmdir("") == static_cast<int>(0x80020002u));
Require(sceKernelMkdir("", 0700) == static_cast<int>(0x80020002u));
const auto cwdPermissions = std::filesystem::status(".").permissions();
Require(sceKernelChmod_nid_postfix("", static_cast<unsigned short>(cwdPermissions) & 07777) == static_cast<int>(0x80020002u));
Require(sceKernelTruncate_nid_postfix("", 0) == static_cast<int>(0x80020002u));
const auto cwdWriteTime = std::filesystem::last_write_time(".");
const int emptyUtimes = sceKernelUtimes_nid_postfix("", nullptr);
std::error_code restoreTimeError;
std::filesystem::last_write_time(".", cwdWriteTime, restoreTimeError);
Require(!restoreTimeError);
Require(emptyUtimes == static_cast<int>(0x80020002u));
Require(stat_nid_postfix(presentName.c_str(), &status) == 0 && status.st_size == 5);
Require(stat_nid_postfix(missingName.c_str(), &status) == -1 && *__error_nid_postfix() == 2);
Require(sceKernelStat(missingName.c_str(), &status) == static_cast<int>(0x80020002u));
@ -478,6 +496,7 @@ int main() {
Require(rmdir_nid_postfix(nullptr) == -1 && *__error_nid_postfix() == 14);
Require(unlink_nid_postfix(missingName.c_str()) == -1 && *__error_nid_postfix() == 2);
Require(sceKernelUnlink(missingName.c_str()) == static_cast<int>(0x80020002u));
Require(sceKernelUnlink("") == static_cast<int>(0x80020002u));
Require(unlink_nid_postfix("") == -1 && *__error_nid_postfix() == 2);
Require(unlink_nid_postfix(nullptr) == -1 && *__error_nid_postfix() == 14);
Require(unlink_nid_postfix(rootName.c_str()) == -1 && *__error_nid_postfix() == 1 && std::filesystem::is_directory(root));