Skip to content

littlefs: Fix issue with trailing dots in file paths #6774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
100 changes: 30 additions & 70 deletions features/filesystem/littlefs/littlefs/lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,26 +783,19 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
lfs_entry_t *entry, const char **path) {
const char *pathname = *path;
size_t pathlen;
entry->d.type = LFS_TYPE_DIR;
entry->d.elen = sizeof(entry->d) - 4;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will sizeof(entry->d) be ever < 4? Will that be corner case considering elen is uint8_t?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the prefix for the entry stored on disk is a 4 byte header. If entry->d is less than 4, than the struct is malformed.

Also GCC is actually smart enough to warn on underflow for constants like these.

entry->d.alen = 0;
entry->d.nlen = 0;
entry->d.u.dir[0] = lfs->root[0];
entry->d.u.dir[1] = lfs->root[1];

while (true) {
nextname:
nextname:
// skip slashes
pathname += strspn(pathname, "/");
pathlen = strcspn(pathname, "/");

// special case for root dir
if (pathname[0] == '\0') {
*entry = (lfs_entry_t){
.d.type = LFS_TYPE_DIR,
.d.elen = sizeof(entry->d) - 4,
.d.alen = 0,
.d.nlen = 0,
.d.u.dir[0] = lfs->root[0],
.d.u.dir[1] = lfs->root[1],
};
return 0;
}

// skip '.' and root '..'
if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
(pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
Expand Down Expand Up @@ -834,10 +827,25 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
suffix += sufflen;
}

// found path
if (pathname[0] == '\0') {
return 0;
}

// update what we've found
*path = pathname;

// find path
// continue on if we hit a directory
if (entry->d.type != LFS_TYPE_DIR) {
return LFS_ERR_NOTDIR;
}

int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir);
if (err) {
return err;
}

// find entry matching name
while (true) {
int err = lfs_dir_next(lfs, dir, entry);
if (err) {
Expand Down Expand Up @@ -873,21 +881,8 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
entry->d.type &= ~0x80;
}

// to next name
pathname += pathlen;
pathname += strspn(pathname, "/");
if (pathname[0] == '\0') {
return 0;
}

// continue on if we hit a directory
if (entry->d.type != LFS_TYPE_DIR) {
return LFS_ERR_NOTDIR;
}

int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir);
if (err) {
return err;
}
}
}

Expand All @@ -904,13 +899,8 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {

// fetch parent directory
lfs_dir_t cwd;
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
if (err) {
return err;
}

lfs_entry_t entry;
err = lfs_dir_find(lfs, &cwd, &entry, &path);
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) {
return err ? err : LFS_ERR_EXIST;
}
Expand Down Expand Up @@ -954,13 +944,8 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
dir->pair[0] = lfs->root[0];
dir->pair[1] = lfs->root[1];

int err = lfs_dir_fetch(lfs, dir, dir->pair);
if (err) {
return err;
}

lfs_entry_t entry;
err = lfs_dir_find(lfs, dir, &entry, &path);
int err = lfs_dir_find(lfs, dir, &entry, &path);
if (err) {
return err;
} else if (entry.d.type != LFS_TYPE_DIR) {
Expand Down Expand Up @@ -1302,13 +1287,8 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,

// allocate entry for file if it doesn't exist
lfs_dir_t cwd;
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
if (err) {
return err;
}

lfs_entry_t entry;
err = lfs_dir_find(lfs, &cwd, &entry, &path);
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) {
return err;
}
Expand Down Expand Up @@ -1814,13 +1794,8 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
/// General fs operations ///
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
lfs_dir_t cwd;
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
if (err) {
return err;
}

lfs_entry_t entry;
err = lfs_dir_find(lfs, &cwd, &entry, &path);
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
if (err) {
return err;
}
Expand Down Expand Up @@ -1855,13 +1830,8 @@ int lfs_remove(lfs_t *lfs, const char *path) {
}

lfs_dir_t cwd;
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
if (err) {
return err;
}

lfs_entry_t entry;
err = lfs_dir_find(lfs, &cwd, &entry, &path);
int err = lfs_dir_find(lfs, &cwd, &entry, &path);
if (err) {
return err;
}
Expand Down Expand Up @@ -1916,24 +1886,14 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {

// find old entry
lfs_dir_t oldcwd;
int err = lfs_dir_fetch(lfs, &oldcwd, lfs->root);
if (err) {
return err;
}

lfs_entry_t oldentry;
err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
int err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
if (err) {
return err;
}

// allocate new entry
lfs_dir_t newcwd;
err = lfs_dir_fetch(lfs, &newcwd, lfs->root);
if (err) {
return err;
}

lfs_entry_t preventry;
err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath);
if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) {
Expand Down
16 changes: 16 additions & 0 deletions features/filesystem/littlefs/littlefs/tests/test_paths.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ tests/test.py << TEST
lfs_unmount(&lfs) => 0;
TEST

echo "--- Trailing dot path tests ---"
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "tea/hottea/", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "tea/hottea/.", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "tea/hottea/./.", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "tea/hottea/..", &info) => 0;
strcmp(info.name, "tea") => 0;
lfs_stat(&lfs, "tea/hottea/../.", &info) => 0;
strcmp(info.name, "tea") => 0;
lfs_unmount(&lfs) => 0;
TEST

echo "--- Root dot dot path tests ---"
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;
Expand Down