فهرست منبع

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
Christopher Haster 6 سال پیش
والد
کامیت
10dfc36f08
2فایلهای تغییر یافته به همراه27 افزوده شده و 2 حذف شده
  1. 3 2
      lfs.c
  2. 24 0
      tests/test_paths.sh

+ 3 - 2
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;

+ 24 - 0
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