Browse Source

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 years ago
parent
commit
a83b2fe463
2 changed files with 64 additions and 0 deletions
  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);
     size = lfs_min(size, file->size - file->pos);
     nsize = size;
     nsize = size;
 
 
@@ -1432,6 +1437,19 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
         file->pos = file->size;
         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) {
     while (nsize > 0) {
         // check if we need a new block
         // check if we need a new block
         if (!(file->flags & LFS_F_WRITING) ||
         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) {
     if (whence == LFS_SEEK_SET) {
         file->pos = off;
         file->pos = off;
     } else if (whence == LFS_SEEK_CUR) {
     } else if (whence == LFS_SEEK_CUR) {
+        if (-off > file->pos) {
+            return LFS_ERR_INVAL;
+        }
+
         file->pos = file->pos + off;
         file->pos = file->pos + off;
     } else if (whence == LFS_SEEK_END) {
     } else if (whence == LFS_SEEK_END) {
+        if (-off > file->size) {
+            return LFS_ERR_INVAL;
+        }
+
         file->pos = file->size + off;
         file->pos = file->size + off;
     }
     }
 
 

+ 38 - 0
tests/test_seek.sh

@@ -305,5 +305,43 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 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 ---"
 echo "--- Results ---"
 tests/stats.py
 tests/stats.py