Fixed several issues with compat flag parsing
- Fixed issue where some overflowed compat flags could end up ignored.
A simple typo: incrementing by the unrelated d variable, meant we
were skipping overflowed compat flags whenever the previous logic sets
d > 1.
- Fixed issue where any zero padding was treated as overflowed compat
flags.
Note this hid the previous issue from our tests.
Added more tests to prevent a regression here. Letting bad compat flag
parsing through would be _very_ annoying in the future.
Code changes:
code stack ctx
before: 38148 2608 752
after: 38084 (-0.2%) 2608 (+0.0%) 752 (+0.0%)
This commit is contained in:
@@ -13471,16 +13471,16 @@ static int lfsr_data_readrcompat(lfs_t *lfs, lfsr_data_t *data,
|
|||||||
//
|
//
|
||||||
// we don't really care about performance here
|
// we don't really care about performance here
|
||||||
while (lfsr_data_size(*data) > 0) {
|
while (lfsr_data_size(*data) > 0) {
|
||||||
lfs_scmp_t cmp = lfsr_data_cmp(lfs, *data, (uint8_t[]){0}, 1);
|
uint8_t b;
|
||||||
if (cmp < 0) {
|
lfs_ssize_t d = lfsr_data_read(lfs, data, &b, 1);
|
||||||
return cmp;
|
if (d < 0) {
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmp != LFS_CMP_EQ) {
|
if (b != 0x00) {
|
||||||
*rcompat |= LFSR_RCOMPAT_OVERFLOW;
|
*rcompat |= LFSR_RCOMPAT_OVERFLOW;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = LFSR_DATA_SLICE(*data, d, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+118
-3
@@ -703,6 +703,8 @@ code = '''
|
|||||||
|
|
||||||
# these are just a bit harder to detect
|
# these are just a bit harder to detect
|
||||||
[cases.test_mount_incompat_rcompat_overflow]
|
[cases.test_mount_incompat_rcompat_overflow]
|
||||||
|
defines.OVERFLOW = 72
|
||||||
|
defines.FLAG = 'range(72)'
|
||||||
in = 'lfs.c'
|
in = 'lfs.c'
|
||||||
code = '''
|
code = '''
|
||||||
// create a superblock
|
// create a superblock
|
||||||
@@ -713,12 +715,16 @@ code = '''
|
|||||||
//
|
//
|
||||||
// note we're messing around with internals to do this! this
|
// note we're messing around with internals to do this! this
|
||||||
// is not a user API
|
// is not a user API
|
||||||
|
uint8_t overflow[OVERFLOW];
|
||||||
|
memset(overflow, 0, sizeof(overflow));
|
||||||
|
overflow[FLAG / 8] |= 1 << (FLAG % 8);
|
||||||
|
|
||||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
||||||
LFSR_RAT_CAT(
|
LFSR_RAT_CAT(
|
||||||
LFSR_TAG_RCOMPAT, 0,
|
LFSR_TAG_RCOMPAT, 0,
|
||||||
LFSR_DATA_RCOMPAT(LFSR_RCOMPAT_COMPAT),
|
LFSR_DATA_RCOMPAT(LFSR_RCOMPAT_COMPAT),
|
||||||
LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0;
|
LFSR_DATA_BUF(overflow, sizeof(overflow))))) => 0;
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
// mount should now fail
|
// mount should now fail
|
||||||
@@ -727,22 +733,31 @@ code = '''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
[cases.test_mount_incompat_wcompat_overflow]
|
[cases.test_mount_incompat_wcompat_overflow]
|
||||||
|
defines.OVERFLOW = 72
|
||||||
|
defines.FLAG = 'range(72)'
|
||||||
in = 'lfs.c'
|
in = 'lfs.c'
|
||||||
code = '''
|
code = '''
|
||||||
// create a superblock
|
// create a superblock
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
|
|
||||||
|
uint8_t flags[9] = {0};
|
||||||
|
flags[FLAG / 8] |= 1 << (FLAG % 8);
|
||||||
|
|
||||||
// set a really far wcompat flag
|
// set a really far wcompat flag
|
||||||
//
|
//
|
||||||
// note we're messing around with internals to do this! this
|
// note we're messing around with internals to do this! this
|
||||||
// is not a user API
|
// is not a user API
|
||||||
|
uint8_t overflow[OVERFLOW];
|
||||||
|
memset(overflow, 0, sizeof(overflow));
|
||||||
|
overflow[FLAG / 8] |= 1 << (FLAG % 8);
|
||||||
|
|
||||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
||||||
LFSR_RAT_CAT(
|
LFSR_RAT_CAT(
|
||||||
LFSR_TAG_WCOMPAT, 0,
|
LFSR_TAG_WCOMPAT, 0,
|
||||||
LFSR_DATA_WCOMPAT(LFSR_WCOMPAT_COMPAT),
|
LFSR_DATA_WCOMPAT(LFSR_WCOMPAT_COMPAT),
|
||||||
LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0;
|
LFSR_DATA_BUF(overflow, sizeof(overflow))))) => 0;
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
// mount should now fail
|
// mount should now fail
|
||||||
@@ -754,6 +769,8 @@ code = '''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
[cases.test_mount_incompat_ocompat_overflow]
|
[cases.test_mount_incompat_ocompat_overflow]
|
||||||
|
defines.OVERFLOW = 72
|
||||||
|
defines.FLAG = 'range(72)'
|
||||||
in = 'lfs.c'
|
in = 'lfs.c'
|
||||||
code = '''
|
code = '''
|
||||||
// create a superblock
|
// create a superblock
|
||||||
@@ -764,12 +781,16 @@ code = '''
|
|||||||
//
|
//
|
||||||
// note we're messing around with internals to do this! this
|
// note we're messing around with internals to do this! this
|
||||||
// is not a user API
|
// is not a user API
|
||||||
|
uint8_t overflow[OVERFLOW];
|
||||||
|
memset(overflow, 0, sizeof(overflow));
|
||||||
|
overflow[FLAG / 8] |= 1 << (FLAG % 8);
|
||||||
|
|
||||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
||||||
LFSR_RAT_CAT(
|
LFSR_RAT_CAT(
|
||||||
LFSR_TAG_OCOMPAT, 0,
|
LFSR_TAG_OCOMPAT, 0,
|
||||||
LFSR_DATA_OCOMPAT(LFSR_OCOMPAT_COMPAT),
|
LFSR_DATA_OCOMPAT(LFSR_OCOMPAT_COMPAT),
|
||||||
LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0;
|
LFSR_DATA_BUF(overflow, sizeof(overflow))))) => 0;
|
||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
// mount should _not_ fail, ocompat should always be ignored
|
// mount should _not_ fail, ocompat should always be ignored
|
||||||
@@ -779,6 +800,100 @@ code = '''
|
|||||||
lfsr_unmount(&lfs) => 0;
|
lfsr_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# but just appending zeros is _not_ an error
|
||||||
|
[cases.test_mount_incompat_rcompat_padding]
|
||||||
|
defines.OVERFLOW = 72
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
// create a superblock
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
|
|
||||||
|
// set a really far rcompat flag
|
||||||
|
//
|
||||||
|
// note we're messing around with internals to do this! this
|
||||||
|
// is not a user API
|
||||||
|
uint8_t overflow[OVERFLOW];
|
||||||
|
memset(overflow, 0, sizeof(overflow));
|
||||||
|
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
||||||
|
LFSR_RAT_CAT(
|
||||||
|
LFSR_TAG_RCOMPAT, 0,
|
||||||
|
LFSR_DATA_RCOMPAT(LFSR_RCOMPAT_COMPAT),
|
||||||
|
LFSR_DATA_BUF(overflow, sizeof(overflow))))) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// mount should _not_ fail, extra zeros should be ignored
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDONLY, CFG) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
|
[cases.test_mount_incompat_wcompat_padding]
|
||||||
|
defines.OVERFLOW = 72
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
// create a superblock
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
|
|
||||||
|
uint8_t flags[9] = {0};
|
||||||
|
flags[FLAG / 8] |= 1 << (FLAG % 8);
|
||||||
|
|
||||||
|
// set a really far wcompat flag
|
||||||
|
//
|
||||||
|
// note we're messing around with internals to do this! this
|
||||||
|
// is not a user API
|
||||||
|
uint8_t overflow[OVERFLOW];
|
||||||
|
memset(overflow, 0, sizeof(overflow));
|
||||||
|
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
||||||
|
LFSR_RAT_CAT(
|
||||||
|
LFSR_TAG_WCOMPAT, 0,
|
||||||
|
LFSR_DATA_WCOMPAT(LFSR_WCOMPAT_COMPAT),
|
||||||
|
LFSR_DATA_BUF(overflow, sizeof(overflow))))) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// mount should _not_ fail, extra zeros should be ignored
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDONLY, CFG) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
|
[cases.test_mount_incompat_ocompat_padding]
|
||||||
|
defines.OVERFLOW = 72
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
// create a superblock
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
|
|
||||||
|
// set a really far ocompat flag
|
||||||
|
//
|
||||||
|
// note we're messing around with internals to do this! this
|
||||||
|
// is not a user API
|
||||||
|
uint8_t overflow[OVERFLOW];
|
||||||
|
memset(overflow, 0, sizeof(overflow));
|
||||||
|
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
|
lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_RATS(
|
||||||
|
LFSR_RAT_CAT(
|
||||||
|
LFSR_TAG_OCOMPAT, 0,
|
||||||
|
LFSR_DATA_OCOMPAT(LFSR_OCOMPAT_COMPAT),
|
||||||
|
LFSR_DATA_BUF(overflow, sizeof(overflow))))) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// mount should _not_ fail, extra zeros should be ignored
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDONLY, CFG) => 0;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
# test that we fail to mount incompatible block sizes
|
# test that we fail to mount incompatible block sizes
|
||||||
[cases.test_mount_incompat_block_size]
|
[cases.test_mount_incompat_block_size]
|
||||||
defines.INC_BLOCK_SIZE = ['BLOCK_SIZE/2', 'BLOCK_SIZE*2']
|
defines.INC_BLOCK_SIZE = ['BLOCK_SIZE/2', 'BLOCK_SIZE*2']
|
||||||
|
|||||||
Reference in New Issue
Block a user