newBlock->mCount++;
}
-void HashList::erase(size_t index)
+void HashList::erase(size_t index, bool itemShouldExist)
{
for (auto it = mBlockList.begin(); it != mBlockList.end();) {
bool haveEntries = false;
++it;
}
}
- assert(false && "item should have been present in cache");
+ if (itemShouldExist) {
+ assert(false && "item should have been present in cache");
+ }
}
size_t HashList::find(size_t start, const Item& item)
{
auto state = mEntryTable.get(index);
assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
- mHashList.erase(index);
size_t span = 1;
if (state == EntryState::WRITTEN) {
return rc;
}
if (item.calculateCrc32() != item.crc32) {
+ mHashList.erase(index, false);
rc = alterEntryState(index, EntryState::ERASED);
--mUsedEntryCount;
++mErasedEntryCount;
return rc;
}
} else {
+ mHashList.erase(index);
span = item.span;
for (ptrdiff_t i = index + span - 1; i >= static_cast<ptrdiff_t>(index); --i) {
if (mEntryTable.get(i) == EntryState::WRITTEN) {
return err;
}
- mHashList.insert(item, i);
-
- // search for potential duplicate item
- size_t duplicateIndex = mHashList.find(0, item);
-
if (item.crc32 != item.calculateCrc32()) {
err = eraseEntryAndSpan(i);
if (err != ESP_OK) {
continue;
}
+ mHashList.insert(item, i);
+
+ // search for potential duplicate item
+ size_t duplicateIndex = mHashList.find(0, item);
if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) {
span = item.span;
return err;
}
- mHashList.insert(item, i);
-
if (item.crc32 != item.calculateCrc32()) {
err = eraseEntryAndSpan(i);
if (err != ESP_OK) {
}
continue;
}
-
+
assert(item.span > 0);
+ mHashList.insert(item, i);
+
size_t span = item.span;
i += span - 1;
}
auto crc32 = item.calculateCrc32();
if (item.crc32 != crc32) {
- eraseEntryAndSpan(i);
+ rc = eraseEntryAndSpan(i);
+ if (rc != ESP_OK) {
+ mState = PageState::INVALID;
+ return rc;
+ }
continue;
}
TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "2", buf, Page::BLOB_MAX_SIZE));
}
+TEST_CASE("Page handles invalid CRC of variable length items", "[nvs][cur]")
+{
+ SpiFlashEmulator emu(4);
+ {
+ Page page;
+ TEST_ESP_OK(page.load(0));
+ char buf[128] = {0};
+ TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "1", buf, sizeof(buf)));
+ }
+ // corrupt header of the item (64 is the offset of the first item in page)
+ uint32_t overwrite_buf = 0;
+ emu.write(64, &overwrite_buf, 4);
+ // load page again
+ {
+ Page page;
+ TEST_ESP_OK(page.load(0));
+ }
+}
+
TEST_CASE("can init PageManager in empty flash", "[nvs]")
{
SpiFlashEmulator emu(4);