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