Skip to content

Commit abaec45

Browse files
committed
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
1 parent f1c430e commit abaec45

File tree

1 file changed

+5
-11
lines changed

1 file changed

+5
-11
lines changed

lfs.c

+5-11
Original file line numberDiff line numberDiff line change
@@ -3664,22 +3664,16 @@ static lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file,
36643664
static lfs_soff_t lfs_file_seek_(lfs_t *lfs, lfs_file_t *file,
36653665
lfs_soff_t off, int whence) {
36663666
// find new pos
3667+
//
3668+
// fortunately for us, littlefs is limited to 31-bit file sizes, so we
3669+
// don't have to worry too much about integer overflow
36673670
lfs_off_t npos = file->pos;
36683671
if (whence == LFS_SEEK_SET) {
36693672
npos = off;
36703673
} else if (whence == LFS_SEEK_CUR) {
3671-
if ((lfs_soff_t)file->pos + off < 0) {
3672-
return LFS_ERR_INVAL;
3673-
} else {
3674-
npos = file->pos + off;
3675-
}
3674+
npos = file->pos + (lfs_off_t)off;
36763675
} else if (whence == LFS_SEEK_END) {
3677-
lfs_soff_t res = lfs_file_size_(lfs, file) + off;
3678-
if (res < 0) {
3679-
return LFS_ERR_INVAL;
3680-
} else {
3681-
npos = res;
3682-
}
3676+
npos = (lfs_off_t)lfs_file_size_(lfs, file) + (lfs_off_t)off;
36833677
}
36843678

36853679
if (npos > lfs->file_max) {

0 commit comments

Comments
 (0)