Parcourir la source

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
Christopher Haster il y a 1 an
Parent
commit
abaec45652
1 fichiers modifiés avec 5 ajouts et 11 suppressions
  1. 5 11
      lfs.c

+ 5 - 11
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) {