@@ -405,3 +405,111 @@ code = '''
405405 lfs_file_close(&lfs, &file) => 0;
406406 lfs_unmount(&lfs) => 0;
407407'''
408+
409+
410+ # test possible overflow/underflow conditions
411+ #
412+ # note these need -fsanitize=undefined to consistently detect
413+ # overflow/underflow conditions
414+
415+ [cases .test_seek_filemax ]
416+ code = '''
417+ lfs_t lfs;
418+ lfs_format(&lfs, cfg) => 0;
419+ lfs_mount(&lfs, cfg) => 0;
420+ lfs_file_t file;
421+ lfs_file_open(&lfs, &file, "kitty",
422+ LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
423+ uint8_t buffer[1024];
424+ strcpy((char*)buffer, "kittycatcat");
425+ size_t size = strlen((char*)buffer);
426+ lfs_file_write(&lfs, &file, buffer, size) => size;
427+
428+ // seek with LFS_SEEK_SET
429+ lfs_file_seek(&lfs, &file, LFS_FILE_MAX, LFS_SEEK_SET) => LFS_FILE_MAX;
430+
431+ // seek with LFS_SEEK_CUR
432+ lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => LFS_FILE_MAX;
433+
434+ // the file hasn't changed size, so seek end takes us back to the offset=0
435+ lfs_file_seek(&lfs, &file, +10, LFS_SEEK_END) => size+10;
436+
437+ lfs_file_close(&lfs, &file) => 0;
438+ lfs_unmount(&lfs) => 0;
439+ '''
440+
441+ [cases .test_seek_underflow ]
442+ code = '''
443+ lfs_t lfs;
444+ lfs_format(&lfs, cfg) => 0;
445+ lfs_mount(&lfs, cfg) => 0;
446+ lfs_file_t file;
447+ lfs_file_open(&lfs, &file, "kitty",
448+ LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
449+ uint8_t buffer[1024];
450+ strcpy((char*)buffer, "kittycatcat");
451+ size_t size = strlen((char*)buffer);
452+ lfs_file_write(&lfs, &file, buffer, size) => size;
453+
454+ // underflow with LFS_SEEK_CUR, should error
455+ lfs_file_seek(&lfs, &file, -(size+10), LFS_SEEK_CUR) => LFS_ERR_INVAL;
456+ lfs_file_seek(&lfs, &file, -LFS_FILE_MAX, LFS_SEEK_CUR) => LFS_ERR_INVAL;
457+ lfs_file_seek(&lfs, &file, -(size+LFS_FILE_MAX), LFS_SEEK_CUR)
458+ => LFS_ERR_INVAL;
459+
460+ // underflow with LFS_SEEK_END, should error
461+ lfs_file_seek(&lfs, &file, -(size+10), LFS_SEEK_END) => LFS_ERR_INVAL;
462+ lfs_file_seek(&lfs, &file, -LFS_FILE_MAX, LFS_SEEK_END) => LFS_ERR_INVAL;
463+ lfs_file_seek(&lfs, &file, -(size+LFS_FILE_MAX), LFS_SEEK_END)
464+ => LFS_ERR_INVAL;
465+
466+ // file pointer should not have changed
467+ lfs_file_tell(&lfs, &file) => size;
468+
469+ lfs_file_close(&lfs, &file) => 0;
470+ lfs_unmount(&lfs) => 0;
471+ '''
472+
473+ [cases .test_seek_overflow ]
474+ code = '''
475+ lfs_t lfs;
476+ lfs_format(&lfs, cfg) => 0;
477+ lfs_mount(&lfs, cfg) => 0;
478+ lfs_file_t file;
479+ lfs_file_open(&lfs, &file, "kitty",
480+ LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
481+ uint8_t buffer[1024];
482+ strcpy((char*)buffer, "kittycatcat");
483+ size_t size = strlen((char*)buffer);
484+ lfs_file_write(&lfs, &file, buffer, size) => size;
485+
486+ // seek to LFS_FILE_MAX
487+ lfs_file_seek(&lfs, &file, LFS_FILE_MAX, LFS_SEEK_SET) => LFS_FILE_MAX;
488+
489+ // overflow with LFS_SEEK_CUR, should error
490+ lfs_file_seek(&lfs, &file, +10, LFS_SEEK_CUR) => LFS_ERR_INVAL;
491+ lfs_file_seek(&lfs, &file, +LFS_FILE_MAX, LFS_SEEK_CUR) => LFS_ERR_INVAL;
492+
493+ // LFS_SEEK_SET/END don't care about the current file position, but we can
494+ // still overflow with a large offset
495+
496+ // overflow with LFS_SEEK_SET, should error
497+ lfs_file_seek(&lfs, &file,
498+ +((uint32_t)LFS_FILE_MAX+10),
499+ LFS_SEEK_SET) => LFS_ERR_INVAL;
500+ lfs_file_seek(&lfs, &file,
501+ +((uint32_t)LFS_FILE_MAX+(uint32_t)LFS_FILE_MAX),
502+ LFS_SEEK_SET) => LFS_ERR_INVAL;
503+
504+ // overflow with LFS_SEEK_END, should error
505+ lfs_file_seek(&lfs, &file, +(LFS_FILE_MAX-size+10), LFS_SEEK_END)
506+ => LFS_ERR_INVAL;
507+ lfs_file_seek(&lfs, &file, +(LFS_FILE_MAX-size+LFS_FILE_MAX), LFS_SEEK_END)
508+ => LFS_ERR_INVAL;
509+
510+ // file pointer should not have changed
511+ lfs_file_tell(&lfs, &file) => LFS_FILE_MAX;
512+
513+ lfs_file_close(&lfs, &file) => 0;
514+ lfs_unmount(&lfs) => 0;
515+ '''
0 commit comments