mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	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
This commit is contained in:
		
							
								
								
									
										5
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -1414,7 +1414,8 @@ static int lfs_dir_compact(lfs_t *lfs, | |||||||
|     bool relocated = false; |     bool relocated = false; | ||||||
|     bool exhausted = false; |     bool exhausted = false; | ||||||
|  |  | ||||||
|     while (true) { |     // should we split? | ||||||
|  |     while (end - begin > 1) { | ||||||
|         // find size |         // find size | ||||||
|         lfs_size_t size = 0; |         lfs_size_t size = 0; | ||||||
|         int err = lfs_dir_traverse(lfs, |         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, |         // space is complicated, we need room for tail, crc, gstate, | ||||||
|         // cleanup delete, and we cap at half a block to give room |         // 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, |         if (size <= lfs_min(lfs->cfg->block_size - 36, | ||||||
|                 lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size))) { |                 lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size))) { | ||||||
|             break; |             break; | ||||||
|   | |||||||
| @@ -165,5 +165,29 @@ tests/test.py << TEST | |||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| TEST | 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 ---" | echo "--- Results ---" | ||||||
| tests/stats.py | tests/stats.py | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user