Kaynağa Gözat

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%).
Christopher Haster 8 yıl önce
ebeveyn
işleme
a83b2fe463
2 değiştirilmiş dosya ile 64 ekleme ve 0 silme
  1. 26 0
      lfs.c
  2. 38 0
      tests/test_seek.sh

+ 26 - 0
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;
     }
 

+ 38 - 0
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