fix range bug in ix memory mapping #98

This commit is contained in:
Peter Andersson
2016-08-09 19:12:07 +02:00
parent 136a40fa68
commit 1c78cd6207
3 changed files with 84 additions and 22 deletions
+14 -7
View File
@@ -1127,6 +1127,7 @@ s32_t SPIFFS_ix_map(spiffs *fs, spiffs_file fh, spiffs_ix_map *map,
map->map_buf = map_buf;
map->offset = offset;
// nb: spix range includes last
map->start_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
map->end_spix = (offset + len) / SPIFFS_DATA_PAGE_SIZE(fs);
memset(map_buf, 0, sizeof(spiffs_page_ix) * (map->end_spix - map->start_spix + 1));
@@ -1187,29 +1188,34 @@ s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) {
if (spix_diff != 0) {
// move vector
int i;
const s32_t vec_len = map->end_spix - map->start_spix + 1;
const s32_t vec_len = map->end_spix - map->start_spix + 1; // spix range includes last
map->start_spix += spix_diff;
map->end_spix += spix_diff;
if (spix_diff >= vec_len) {
// moving beyond range
memset(&map->map_buf, 0, vec_len * sizeof(spiffs_page_ix));
res = spiffs_populate_ix_map(fs, fd, 0, vec_len);
// populate_ix_map is inclusive
res = spiffs_populate_ix_map(fs, fd, 0, vec_len-1);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} else if (spix_diff > 0) {
// diff positive
for (i = 0; i < vec_len - spix_diff - 1; i++) {
for (i = 0; i < vec_len - spix_diff; i++) {
map->map_buf[i] = map->map_buf[i + spix_diff];
}
memset(&map->map_buf[vec_len - spix_diff - 1], 0, spix_diff * sizeof(spiffs_page_ix));
res = spiffs_populate_ix_map(fs, fd, vec_len - spix_diff, vec_len);
// memset is non-inclusive
memset(&map->map_buf[vec_len - spix_diff], 0, spix_diff * sizeof(spiffs_page_ix));
// populate_ix_map is inclusive
res = spiffs_populate_ix_map(fs, fd, vec_len - spix_diff, vec_len-1);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} else {
// diff negative
for (i = vec_len - 1; i >= -spix_diff; i--) {
map->map_buf[i] = map->map_buf[i + spix_diff];
}
// memset is non-inclusive
memset(&map->map_buf[0], 0, -spix_diff * sizeof(spiffs_page_ix));
res = spiffs_populate_ix_map(fs, fd, 0, spix_diff);
// populate_ix_map is inclusive
res = spiffs_populate_ix_map(fs, fd, 0, -spix_diff - 1);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
@@ -1221,7 +1227,8 @@ s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) {
s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes) {
SPIFFS_API_CHECK_CFG(fs);
return (bytes + (SPIFFS_DATA_PAGE_SIZE(fs) -1) ) / SPIFFS_DATA_PAGE_SIZE(fs);
// always add one extra page, the offset might change to the middle of a page
return (bytes + SPIFFS_DATA_PAGE_SIZE(fs) ) / SPIFFS_DATA_PAGE_SIZE(fs);
}
s32_t SPIFFS_ix_map_entries_to_bytes(spiffs *fs, u32_t map_page_ix_entries) {
+1
View File
@@ -708,6 +708,7 @@ static s32_t spiffs_populate_ix_map_v(
return res;
}
// populates index map, from vector entry start to vector entry end, inclusive
s32_t spiffs_populate_ix_map(spiffs *fs, spiffs_fd *fd, u32_t vec_entry_start, u32_t vec_entry_end) {
s32_t res;
spiffs_ix_map *map = fd->ix_map;
+69 -15
View File
@@ -2047,37 +2047,78 @@ TEST(ix_map_remap)
fd1 = SPIFFS_open(FS, "1", SPIFFS_O_RDONLY, 0);
TEST_CHECK_GT(fd1, 0);
printf(".. corresponding pix entries: %i\n", SPIFFS_bytes_to_ix_map_entries(FS, size));
TEST_CHECK_EQ(SPIFFS_bytes_to_ix_map_entries(FS, size), size_pages);
printf(".. corresponding pix entries: %i\n", SPIFFS_bytes_to_ix_map_entries(FS, size) + 1);
TEST_CHECK_EQ(SPIFFS_bytes_to_ix_map_entries(FS, size), size_pages + 1);
// map index to memory
// move around, check validity
const int entries = SPIFFS_bytes_to_ix_map_entries(FS, size/2);
spiffs_ix_map map;
spiffs_page_ix ixbuf[entries];
spiffs_page_ix ixbuf_ref[entries];
// add one extra for stack safeguarding
spiffs_page_ix ixbuf[entries+1];
spiffs_page_ix ixbuf_ref[entries+1];
const spiffs_page_ix canary = (spiffs_page_ix)0x87654321;
memset(ixbuf, 0xee, sizeof(ixbuf));
ixbuf[entries] = canary;
res = SPIFFS_ix_map(FS, fd1, &map, 0, size/2, ixbuf);
TEST_CHECK_GE(res, SPIFFS_OK);
memcpy(ixbuf_ref, ixbuf, sizeof(ixbuf));
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf[i]);
}
printf("\n");
memcpy(ixbuf_ref, ixbuf, sizeof(spiffs_page_ix) * entries);
TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, 0), SPIFFS_OK);
TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(ixbuf)));
TEST_CHECK_EQ(canary, ixbuf[entries]);
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf[i]);
}
printf("\n");
TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(spiffs_page_ix) * entries));
TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, SPIFFS_DATA_PAGE_SIZE(FS)), SPIFFS_OK);
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf[i]);
}
printf("\n");
TEST_CHECK_EQ(canary, ixbuf[entries]);
TEST_CHECK_EQ(0, memcmp(&ixbuf_ref[1], ixbuf, sizeof(spiffs_page_ix) * (entries-1)));
TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, 0), SPIFFS_OK);
TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(ixbuf)));
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf[i]);
}
printf("\n");
TEST_CHECK_EQ(canary, ixbuf[entries]);
TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(spiffs_page_ix) * entries));
TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, size/2), SPIFFS_OK);
TEST_CHECK_EQ(canary, ixbuf[entries]);
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf_ref[i]);
}
printf("\n");
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf[i]);
}
printf("\n");
int matches = 0;
for (i = 0; i < entries; i++) {
int j;
for (j = 0; j < entries; j++) {
TEST_CHECK_NEQ(ixbuf_ref[i], ixbuf[j]);
if (ixbuf_ref[i] == ixbuf[i]) {
matches++;
}
}
}
TEST_CHECK_LE(matches, 1);
return TEST_RES_OK;
}
@@ -2180,15 +2221,18 @@ TEST(ix_map_beyond)
const int entries = SPIFFS_bytes_to_ix_map_entries(FS, size);
spiffs_ix_map map;
spiffs_page_ix ixbuf[entries];
printf("map has %i entries\n", entries);
printf("map 100-200%%\n");
res = SPIFFS_ix_map(FS, fd, &map, size, size*2, ixbuf);
res = SPIFFS_ix_map(FS, fd, &map, size, size, ixbuf);
TEST_CHECK_GE(res, SPIFFS_OK);
// make sure map is empty
printf("make sure map is empty\n");
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf[i]);
TEST_CHECK_EQ(ixbuf[i], 0);
}
printf("\n");
printf("elongate by 100%%\n");
for (i = 0; i < size_pages; i++) {
@@ -2203,19 +2247,25 @@ TEST(ix_map_beyond)
size = s.size;
printf("file elongated, size: %i..\n", size);
// make sure map is non-empty
printf("make sure map is full but for one element\n");
int zeroed = 0;
for (i = 0; i < entries; i++) {
TEST_CHECK_NEQ(ixbuf[i], 0);
printf("%04x ", ixbuf[i]);
if (ixbuf[i] == 0) zeroed++;
}
printf("\n");
TEST_CHECK_LE(zeroed, 1);
printf("remap till end\n");
TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd, size), SPIFFS_OK);
// make sure map is empty but for one element
printf("make sure map is empty but for one element\n");
int nonzero = 0;
for (i = 0; i < entries; i++) {
printf("%04x ", ixbuf[i]);
if (ixbuf[i]) nonzero++;
}
printf("\n");
TEST_CHECK_LE(nonzero, 1);
printf("elongate again, by other fd\n");
@@ -2230,10 +2280,14 @@ TEST(ix_map_beyond)
}
TEST_CHECK_GE(SPIFFS_close(FS, fd2), SPIFFS_OK);
// make sure map is non-empty
printf("make sure map is full but for one element\n");
zeroed = 0;
for (i = 0; i < entries; i++) {
TEST_CHECK_NEQ(ixbuf[i], 0);
printf("%04x ", ixbuf[i]);
if (ixbuf[i] == 0) zeroed++;
}
printf("\n");
TEST_CHECK_LE(zeroed, 1);
return TEST_RES_OK;
}