Skip to content

Commit a83b2fe

Browse files
committed
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%).
1 parent a8fa5e6 commit a83b2fe

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

lfs.c

+26
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,11 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
13771377
}
13781378
}
13791379

1380+
if (file->pos >= file->size) {
1381+
// eof if past end
1382+
return 0;
1383+
}
1384+
13801385
size = lfs_min(size, file->size - file->pos);
13811386
nsize = size;
13821387

@@ -1432,6 +1437,19 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
14321437
file->pos = file->size;
14331438
}
14341439

1440+
if (!(file->flags & LFS_F_WRITING) && file->pos > file->size) {
1441+
// fill with zeros
1442+
lfs_off_t pos = file->pos;
1443+
file->pos = file->size;
1444+
1445+
while (file->pos < pos) {
1446+
lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1);
1447+
if (res < 0) {
1448+
return res;
1449+
}
1450+
}
1451+
}
1452+
14351453
while (nsize > 0) {
14361454
// check if we need a new block
14371455
if (!(file->flags & LFS_F_WRITING) ||
@@ -1506,8 +1524,16 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
15061524
if (whence == LFS_SEEK_SET) {
15071525
file->pos = off;
15081526
} else if (whence == LFS_SEEK_CUR) {
1527+
if (-off > file->pos) {
1528+
return LFS_ERR_INVAL;
1529+
}
1530+
15091531
file->pos = file->pos + off;
15101532
} else if (whence == LFS_SEEK_END) {
1533+
if (-off > file->size) {
1534+
return LFS_ERR_INVAL;
1535+
}
1536+
15111537
file->pos = file->size + off;
15121538
}
15131539

tests/test_seek.sh

+38
Original file line numberDiff line numberDiff line change
@@ -305,5 +305,43 @@ tests/test.py << TEST
305305
lfs_unmount(&lfs) => 0;
306306
TEST
307307

308+
echo "--- Out-of-bounds seek ---"
309+
tests/test.py << TEST
310+
lfs_mount(&lfs, &cfg) => 0;
311+
lfs_file_open(&lfs, &file[0], "hello/kitty42", LFS_O_RDWR) => 0;
312+
313+
size = strlen("kittycatcat");
314+
lfs_file_size(&lfs, &file[0]) => $LARGESIZE*size;
315+
lfs_file_seek(&lfs, &file[0],
316+
($LARGESIZE+$SMALLSIZE)*size, LFS_SEEK_SET) => 0;
317+
lfs_file_read(&lfs, &file[0], buffer, size) => 0;
318+
319+
memcpy(buffer, "porcupineee", size);
320+
lfs_file_write(&lfs, &file[0], buffer, size) => size;
321+
322+
lfs_file_seek(&lfs, &file[0],
323+
($LARGESIZE+$SMALLSIZE)*size, LFS_SEEK_SET) =>
324+
($LARGESIZE+$SMALLSIZE+1)*size;
325+
lfs_file_read(&lfs, &file[0], buffer, size) => size;
326+
memcmp(buffer, "porcupineee", size) => 0;
327+
328+
lfs_file_seek(&lfs, &file[0],
329+
$LARGESIZE*size, LFS_SEEK_SET) =>
330+
($LARGESIZE+$SMALLSIZE+1)*size;
331+
lfs_file_read(&lfs, &file[0], buffer, size) => size;
332+
memcmp(buffer, "\0\0\0\0\0\0\0\0\0\0\0", size) => 0;
333+
334+
lfs_file_seek(&lfs, &file[0],
335+
-(($LARGESIZE+$SMALLSIZE)*size), LFS_SEEK_CUR) => LFS_ERR_INVAL;
336+
lfs_file_tell(&lfs, &file[0]) => ($LARGESIZE+1)*size;
337+
338+
lfs_file_seek(&lfs, &file[0],
339+
-(($LARGESIZE+2*$SMALLSIZE)*size), LFS_SEEK_END) => LFS_ERR_INVAL;
340+
lfs_file_tell(&lfs, &file[0]) => ($LARGESIZE+1)*size;
341+
342+
lfs_file_close(&lfs, &file[0]) => 0;
343+
lfs_unmount(&lfs) => 0;
344+
TEST
345+
308346
echo "--- Results ---"
309347
tests/stats.py

0 commit comments

Comments
 (0)