paths: Reject empty paths

Before this, the empty path ("") was treated as an alias for the root.
This was unintentional and just a side-effect of how the path parser
worked.

Now, the empty path should always result in LFS_ERR_INVAL:

- before: lfs_stat("") => 0
- after:  lfs_stat("") => LFS_ERR_INVAL
This commit is contained in:
Christopher Haster
2024-11-23 18:25:40 -06:00
parent 815f0d85a5
commit 80ca1ea300
2 changed files with 58 additions and 21 deletions

7
lfs.c
View File

@@ -1492,6 +1492,11 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
dir->tail[0] = lfs->root[0];
dir->tail[1] = lfs->root[1];
// empty paths are not allowed
if (*name == '\0') {
return LFS_ERR_INVAL;
}
while (true) {
nextname:
// skip slashes if we're a directory
@@ -1538,7 +1543,7 @@ nextname:
}
// found path
if (name[0] == '\0') {
if (*name == '\0') {
return tag;
}

View File

@@ -3216,6 +3216,58 @@ code = '''
lfs_unmount(&lfs) => 0;
'''
# test an empty path, this should error
[cases.test_paths_empty]
defines.DIR = [false, true]
code = '''
lfs_t lfs;
lfs_format(&lfs, cfg) => 0;
lfs_mount(&lfs, cfg) => 0;
struct lfs_info info;
// create empty, this should error
if (DIR) {
lfs_mkdir(&lfs, "") => LFS_ERR_INVAL;
} else {
lfs_file_t file;
lfs_file_open(&lfs, &file, "",
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL;
}
// stat empty
lfs_stat(&lfs, "", &info) => LFS_ERR_INVAL;
// file open empty, only works on files!
lfs_file_t file;
lfs_file_open(&lfs, &file, "",
LFS_O_RDONLY) => LFS_ERR_INVAL;
// dir open empty, only works on dirs!
lfs_dir_t dir;
lfs_dir_open(&lfs, &dir, "") => LFS_ERR_INVAL;
lfs_dir_close(&lfs, &dir) => 0;
// rename empty, this should error
lfs_rename(&lfs, "", "coffee") => LFS_ERR_INVAL;
lfs_mkdir(&lfs, "coffee") => 0;
lfs_rename(&lfs, "coffee", "") => LFS_ERR_INVAL;
lfs_remove(&lfs, "coffee") => 0;
lfs_rename(&lfs, "", "") => LFS_ERR_INVAL;
// stat empty
lfs_stat(&lfs, "", &info) => LFS_ERR_INVAL;
// remove empty, this should error
lfs_remove(&lfs, "") => LFS_ERR_INVAL;
// stat empty
lfs_stat(&lfs, "", &info) => LFS_ERR_INVAL;
lfs_unmount(&lfs) => 0;
'''
# root operations
#
# POSIX deviations:
@@ -3294,7 +3346,6 @@ code = '''
// create root, this should error
if (DIR) {
lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
lfs_mkdir(&lfs, "") => LFS_ERR_EXIST;
lfs_mkdir(&lfs, ".") => LFS_ERR_EXIST;
lfs_mkdir(&lfs, "./") => LFS_ERR_EXIST;
lfs_mkdir(&lfs, "/.") => LFS_ERR_EXIST;
@@ -3303,8 +3354,6 @@ code = '''
lfs_file_t file;
lfs_file_open(&lfs, &file, "/",
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, "",
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, ".",
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, "./",
@@ -3319,9 +3368,6 @@ code = '''
lfs_stat(&lfs, "/", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
lfs_stat(&lfs, "", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
lfs_stat(&lfs, ".", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
@@ -3339,8 +3385,6 @@ code = '''
lfs_file_t file;
lfs_file_open(&lfs, &file, "/",
LFS_O_RDONLY) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, "",
LFS_O_RDONLY) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, ".",
LFS_O_RDONLY) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, "./",
@@ -3354,8 +3398,6 @@ code = '''
lfs_dir_t dir;
lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_close(&lfs, &dir) => 0;
lfs_dir_open(&lfs, &dir, "") => 0;
lfs_dir_close(&lfs, &dir) => 0;
lfs_dir_open(&lfs, &dir, ".") => 0;
lfs_dir_close(&lfs, &dir) => 0;
lfs_dir_open(&lfs, &dir, "./") => 0;
@@ -3367,7 +3409,6 @@ code = '''
// rename root, this should error
lfs_rename(&lfs, "/", "coffee") => LFS_ERR_INVAL;
lfs_rename(&lfs, "", "coffee") => LFS_ERR_INVAL;
lfs_rename(&lfs, ".", "coffee") => LFS_ERR_INVAL;
lfs_rename(&lfs, "./", "coffee") => LFS_ERR_INVAL;
lfs_rename(&lfs, "/.", "coffee") => LFS_ERR_INVAL;
@@ -3375,7 +3416,6 @@ code = '''
lfs_mkdir(&lfs, "coffee") => 0;
lfs_rename(&lfs, "coffee", "/") => LFS_ERR_INVAL;
lfs_rename(&lfs, "coffee", "") => LFS_ERR_INVAL;
lfs_rename(&lfs, "coffee", ".") => LFS_ERR_INVAL;
lfs_rename(&lfs, "coffee", "./") => LFS_ERR_INVAL;
lfs_rename(&lfs, "coffee", "/.") => LFS_ERR_INVAL;
@@ -3383,7 +3423,6 @@ code = '''
lfs_remove(&lfs, "coffee") => 0;
lfs_rename(&lfs, "/", "/") => LFS_ERR_INVAL;
lfs_rename(&lfs, "", "") => LFS_ERR_INVAL;
lfs_rename(&lfs, ".", ".") => LFS_ERR_INVAL;
lfs_rename(&lfs, "..", "..") => LFS_ERR_INVAL;
lfs_rename(&lfs, "./", "./") => LFS_ERR_INVAL;
@@ -3394,9 +3433,6 @@ code = '''
lfs_stat(&lfs, "/", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
lfs_stat(&lfs, "", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
lfs_stat(&lfs, ".", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
@@ -3412,7 +3448,6 @@ code = '''
// remove root, this should error
lfs_remove(&lfs, "/") => LFS_ERR_INVAL;
lfs_remove(&lfs, "") => LFS_ERR_INVAL;
lfs_remove(&lfs, ".") => LFS_ERR_INVAL;
lfs_remove(&lfs, "./") => LFS_ERR_INVAL;
lfs_remove(&lfs, "/.") => LFS_ERR_INVAL;
@@ -3422,9 +3457,6 @@ code = '''
lfs_stat(&lfs, "/", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
lfs_stat(&lfs, "", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);
lfs_stat(&lfs, ".", &info) => 0;
assert(strcmp(info.name, "/") == 0);
assert(info.type == LFS_TYPE_DIR);