From 614f7b1e68ca796af6074fd21ceb812f3c609fa1 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 28 May 2019 13:55:03 -0500 Subject: [PATCH] Fixed accidental truncate after seek on inline files The cause was mistakenly setting file->ctz.size directly instead of file->pos, which file->ctz.size gets overwritten with later in lfs_file_flush. Also added better seek test cases specifically for inline files. This should also catch most of the inline corner cases related to lfs_file_size/lfs_file_tell. Found by ebinans --- lfs.c | 2 +- tests/test_seek.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/lfs.c b/lfs.c index 8ebf4ed..ca6d587 100644 --- a/lfs.c +++ b/lfs.c @@ -2548,7 +2548,7 @@ relocate: } } } else { - file->ctz.size = lfs_max(file->pos, file->ctz.size); + file->pos = lfs_max(file->pos, file->ctz.size); } // actual file updates diff --git a/tests/test_seek.sh b/tests/test_seek.sh index 2cd711a..1803317 100755 --- a/tests/test_seek.sh +++ b/tests/test_seek.sh @@ -357,5 +357,63 @@ tests/test.py << TEST lfs_unmount(&lfs) => 0; TEST +echo "--- Inline write and seek ---" +for SIZE in $SMALLSIZE $MEDIUMSIZE $LARGESIZE +do +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + lfs_file_open(&lfs, &file[0], "hello/tinykitty$SIZE", + LFS_O_RDWR | LFS_O_CREAT) => 0; + int j = 0; + int k = 0; + + memcpy(buffer, "abcdefghijklmnopqrstuvwxyz", 26); + for (unsigned i = 0; i < $SIZE; i++) { + lfs_file_write(&lfs, &file[0], &buffer[j++ % 26], 1) => 1; + lfs_file_tell(&lfs, &file[0]) => i+1; + lfs_file_size(&lfs, &file[0]) => i+1; + } + + lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_SET) => 0; + lfs_file_tell(&lfs, &file[0]) => 0; + lfs_file_size(&lfs, &file[0]) => $SIZE; + for (unsigned i = 0; i < $SIZE; i++) { + uint8_t c; + lfs_file_read(&lfs, &file[0], &c, 1) => 1; + c => buffer[k++ % 26]; + } + + lfs_file_sync(&lfs, &file[0]) => 0; + lfs_file_tell(&lfs, &file[0]) => $SIZE; + lfs_file_size(&lfs, &file[0]) => $SIZE; + + lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_SET) => 0; + for (unsigned i = 0; i < $SIZE; i++) { + lfs_file_write(&lfs, &file[0], &buffer[j++ % 26], 1) => 1; + lfs_file_tell(&lfs, &file[0]) => i+1; + lfs_file_size(&lfs, &file[0]) => $SIZE; + lfs_file_sync(&lfs, &file[0]) => 0; + lfs_file_tell(&lfs, &file[0]) => i+1; + lfs_file_size(&lfs, &file[0]) => $SIZE; + } + + lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_SET) => 0; + lfs_file_tell(&lfs, &file[0]) => 0; + lfs_file_size(&lfs, &file[0]) => $SIZE; + for (unsigned i = 0; i < $SIZE; i++) { + uint8_t c; + lfs_file_read(&lfs, &file[0], &c, 1) => 1; + c => buffer[k++ % 26]; + } + + lfs_file_sync(&lfs, &file[0]) => 0; + lfs_file_tell(&lfs, &file[0]) => $SIZE; + lfs_file_size(&lfs, &file[0]) => $SIZE; + + lfs_file_close(&lfs, &file[0]) => 0; + lfs_unmount(&lfs) => 0; +TEST +done + echo "--- Results ---" tests/stats.py