From abaec45652a1e8c79f812c3e868f6c1063e06c51 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 24 Sep 2024 13:47:28 -0500 Subject: [PATCH] Fixed seek undefined behavior on signed integer overflow In the previous implementation of lfs_file_seek, we calculated the new offset using signed arithmetic before checking for possible overflow/underflow conditions. This results in undefined behavior in C. Fortunately for us, littlefs is now limited to 31-bit file sizes for API reasons, so we don't have to be too clever here. Doing the arithmetic with unsigned integers and just checking if we're in a valid range afterwards should work. Found by m-kostrzewa and lucic71 --- lfs.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/lfs.c b/lfs.c index d35d5d6d..933f69c7 100644 --- a/lfs.c +++ b/lfs.c @@ -3664,22 +3664,16 @@ static lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file, static lfs_soff_t lfs_file_seek_(lfs_t *lfs, lfs_file_t *file, lfs_soff_t off, int whence) { // find new pos + // + // fortunately for us, littlefs is limited to 31-bit file sizes, so we + // don't have to worry too much about integer overflow lfs_off_t npos = file->pos; if (whence == LFS_SEEK_SET) { npos = off; } else if (whence == LFS_SEEK_CUR) { - if ((lfs_soff_t)file->pos + off < 0) { - return LFS_ERR_INVAL; - } else { - npos = file->pos + off; - } + npos = file->pos + (lfs_off_t)off; } else if (whence == LFS_SEEK_END) { - lfs_soff_t res = lfs_file_size_(lfs, file) + off; - if (res < 0) { - return LFS_ERR_INVAL; - } else { - npos = res; - } + npos = (lfs_off_t)lfs_file_size_(lfs, file) + (lfs_off_t)off; } if (npos > lfs->file_max) {