From 10dfc36f08081274e37133107fff3a14d180b5e4 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 31 Jan 2019 14:54:47 -0600 Subject: [PATCH] Fixed issue with long names causing unbounded recursion This was caused by any commit containing entries large enough to _always_ force a compaction. This would cause littlefs to think that it would need to split infinitely because there was no base case. The fix here is pretty simple: treat any commit with only a single entry as unsplittable. This forces littlefs to first try overcompacting (fitting more in a block than what has optimal runtime), and then failing that return LFS_ERR_NOSPC for higher layers to handle. found by TheLoneWolfling --- lfs.c | 5 +++-- tests/test_paths.sh | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lfs.c b/lfs.c index d4ccb41..c6ff2e9 100644 --- a/lfs.c +++ b/lfs.c @@ -1414,7 +1414,8 @@ static int lfs_dir_compact(lfs_t *lfs, bool relocated = false; bool exhausted = false; - while (true) { + // should we split? + while (end - begin > 1) { // find size lfs_size_t size = 0; int err = lfs_dir_traverse(lfs, @@ -1429,7 +1430,7 @@ static int lfs_dir_compact(lfs_t *lfs, // space is complicated, we need room for tail, crc, gstate, // cleanup delete, and we cap at half a block to give room - // for metadata updates + // for metadata updates. if (size <= lfs_min(lfs->cfg->block_size - 36, lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size))) { break; diff --git a/tests/test_paths.sh b/tests/test_paths.sh index 999001a..b1d41a7 100755 --- a/tests/test_paths.sh +++ b/tests/test_paths.sh @@ -165,5 +165,29 @@ tests/test.py << TEST lfs_unmount(&lfs) => 0; TEST +echo "--- Really big path test ---" +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + memset(buffer, 'w', LFS_NAME_MAX); + buffer[LFS_NAME_MAX+1] = '\0'; + lfs_mkdir(&lfs, (char*)buffer) => 0; + lfs_remove(&lfs, (char*)buffer) => 0; + lfs_file_open(&lfs, &file[0], (char*)buffer, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file[0]) => 0; + lfs_remove(&lfs, (char*)buffer) => 0; + + memcpy(buffer, "coffee/", strlen("coffee/")); + memset(buffer+strlen("coffee/"), 'w', LFS_NAME_MAX); + buffer[strlen("coffee/")+LFS_NAME_MAX+1] = '\0'; + lfs_mkdir(&lfs, (char*)buffer) => 0; + lfs_remove(&lfs, (char*)buffer) => 0; + lfs_file_open(&lfs, &file[0], (char*)buffer, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file[0]) => 0; + lfs_remove(&lfs, (char*)buffer) => 0; + lfs_unmount(&lfs) => 0; +TEST + echo "--- Results ---" tests/stats.py