From a83b2fe4638c92ce6cc475a3c7cc75ca431bb6b8 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 17 Sep 2017 17:57:12 -0500 Subject: [PATCH] Added checks for out-of-bound seeks - out-of-bound read results in eof - out-of-bound write will fill missing area with zeros The write behaviour matches expected posix behaviour, but was under consideration for not being dropped, since littlefs does not support holes, and support of out-of-band seeks adds complexity. However, it turned out filling with zeros was trivial, and only cost an extra 74 bytes of flash (0.48%). --- lfs.c | 26 ++++++++++++++++++++++++++ tests/test_seek.sh | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/lfs.c b/lfs.c index 194d0f8..3f13fd6 100644 --- a/lfs.c +++ b/lfs.c @@ -1377,6 +1377,11 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, } } + if (file->pos >= file->size) { + // eof if past end + return 0; + } + size = lfs_min(size, file->size - file->pos); nsize = size; @@ -1432,6 +1437,19 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, file->pos = file->size; } + if (!(file->flags & LFS_F_WRITING) && file->pos > file->size) { + // fill with zeros + lfs_off_t pos = file->pos; + file->pos = file->size; + + while (file->pos < pos) { + lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1); + if (res < 0) { + return res; + } + } + } + while (nsize > 0) { // check if we need a new block if (!(file->flags & LFS_F_WRITING) || @@ -1506,8 +1524,16 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, if (whence == LFS_SEEK_SET) { file->pos = off; } else if (whence == LFS_SEEK_CUR) { + if (-off > file->pos) { + return LFS_ERR_INVAL; + } + file->pos = file->pos + off; } else if (whence == LFS_SEEK_END) { + if (-off > file->size) { + return LFS_ERR_INVAL; + } + file->pos = file->size + off; } diff --git a/tests/test_seek.sh b/tests/test_seek.sh index 1f70ee3..8b90928 100755 --- a/tests/test_seek.sh +++ b/tests/test_seek.sh @@ -305,5 +305,43 @@ tests/test.py << TEST lfs_unmount(&lfs) => 0; TEST +echo "--- Out-of-bounds seek ---" +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + lfs_file_open(&lfs, &file[0], "hello/kitty42", LFS_O_RDWR) => 0; + + size = strlen("kittycatcat"); + lfs_file_size(&lfs, &file[0]) => $LARGESIZE*size; + lfs_file_seek(&lfs, &file[0], + ($LARGESIZE+$SMALLSIZE)*size, LFS_SEEK_SET) => 0; + lfs_file_read(&lfs, &file[0], buffer, size) => 0; + + memcpy(buffer, "porcupineee", size); + lfs_file_write(&lfs, &file[0], buffer, size) => size; + + lfs_file_seek(&lfs, &file[0], + ($LARGESIZE+$SMALLSIZE)*size, LFS_SEEK_SET) => + ($LARGESIZE+$SMALLSIZE+1)*size; + lfs_file_read(&lfs, &file[0], buffer, size) => size; + memcmp(buffer, "porcupineee", size) => 0; + + lfs_file_seek(&lfs, &file[0], + $LARGESIZE*size, LFS_SEEK_SET) => + ($LARGESIZE+$SMALLSIZE+1)*size; + lfs_file_read(&lfs, &file[0], buffer, size) => size; + memcmp(buffer, "\0\0\0\0\0\0\0\0\0\0\0", size) => 0; + + lfs_file_seek(&lfs, &file[0], + -(($LARGESIZE+$SMALLSIZE)*size), LFS_SEEK_CUR) => LFS_ERR_INVAL; + lfs_file_tell(&lfs, &file[0]) => ($LARGESIZE+1)*size; + + lfs_file_seek(&lfs, &file[0], + -(($LARGESIZE+2*$SMALLSIZE)*size), LFS_SEEK_END) => LFS_ERR_INVAL; + lfs_file_tell(&lfs, &file[0]) => ($LARGESIZE+1)*size; + + lfs_file_close(&lfs, &file[0]) => 0; + lfs_unmount(&lfs) => 0; +TEST + echo "--- Results ---" tests/stats.py