diff --git a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp index 74628f8e65..1da5e8ca80 100644 --- a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp +++ b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -547,8 +547,8 @@ TEST_CASE("readonly handle fails on writing", "[nvs]") TEMPORARILY_DISABLED(f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); // first, creating namespace... TEST_ESP_OK(nvs_open("ro_ns", NVS_READWRITE, &handle_1)); @@ -575,14 +575,13 @@ TEST_CASE("nvs api tests", "[nvs]") const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; TEMPORARILY_DISABLED(f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) - TEST_ESP_ERR(nvs_open("namespace1", NVS_READWRITE, &handle_1), ESP_ERR_NVS_NOT_INITIALIZED); for (uint16_t i = NVS_FLASH_SECTOR; i < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; ++i) { TEMPORARILY_DISABLED(f.emu.erase(i);) } TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); @@ -643,11 +642,11 @@ TEST_CASE("deinit partition doesn't affect other partition's open handles", "[nv TEMPORARILY_DISABLED(f_other.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f_other.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); TEST_ESP_OK(nvs_open_from_partition(OTHER_PARTITION_NAME, "ns", NVS_READWRITE, &handle_1)); @@ -715,8 +714,8 @@ TEST_CASE("nvs iterators tests", "[nvs]") TEMPORARILY_DISABLED(f.emu.erase(i);) } TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); nvs_iterator_t it; nvs_entry_info_t info; @@ -748,8 +747,7 @@ TEST_CASE("nvs iterators tests", "[nvs]") int count = 0; nvs_iterator_t it = nullptr; esp_err_t res = nvs_entry_find(part, name, type, &it); - for (count = 0; res == ESP_OK; count++) - { + for (count = 0; res == ESP_OK; count++) { res = nvs_entry_next(&it); } CHECK(res == ESP_ERR_NVS_NOT_FOUND); // after finishing the loop or if no entry was found to begin with, @@ -858,14 +856,13 @@ TEST_CASE("nvs iterators tests", "[nvs]") nvs_release_iterator(it); } - SECTION("Iterating over multiple pages works correctly") { nvs_handle_t handle_3; const char *name_3 = "namespace3"; const int entries_created = 250; TEST_ESP_OK(nvs_open(name_3, NVS_READWRITE, &handle_3)); - for (size_t i = 0; i < entries_created; i++) { + for (size_t i = 0; i < entries_created; i++) { TEST_ESP_OK(nvs_set_u8(handle_3, to_string(i).c_str(), 123)); } @@ -922,8 +919,8 @@ TEST_CASE("Iterator with not matching type iterates correctly", "[nvs]") TEMPORARILY_DISABLED(f.emu.erase(i);) } TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); // writing string to namespace (a type which spans multiple entries) TEST_ESP_OK(nvs_open(NAMESPACE, NVS_READWRITE, &my_handle)); @@ -936,8 +933,8 @@ TEST_CASE("Iterator with not matching type iterates correctly", "[nvs]") // re-init to trigger cleaning up of broken items -> a corrupted string will be erased nvs_flash_deinit(); TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); CHECK(nvs_entry_find(NVS_DEFAULT_PART_NAME, NAMESPACE, NVS_TYPE_STR, &it) == ESP_OK); nvs_release_iterator(it); @@ -955,8 +952,8 @@ TEST_CASE("wifi test", "[nvs]") const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; TEMPORARILY_DISABLED(f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); nvs_handle_t misc_handle; TEST_ESP_OK(nvs_open("nvs.net80211", NVS_READWRITE, &misc_handle)); @@ -1123,8 +1120,7 @@ public: static_assert(nKeys == sizeof(values) / sizeof(values[0]), ""); auto randomRead = [&](size_t index) -> esp_err_t { - switch (types[index]) - { + switch (types[index]) { case nvs::ItemType::I32: { int32_t val; auto err = nvs_get_i32(handle, keys[index], &val); @@ -1204,8 +1200,7 @@ public: }; auto randomWrite = [&](size_t index) -> esp_err_t { - switch (types[index]) - { + switch (types[index]) { case nvs::ItemType::I32: { int32_t val = static_cast(gen()); @@ -1323,7 +1318,7 @@ public: return ESP_OK; } - esp_err_t handleExternalWriteAtIndex(uint8_t index, const void *value, const size_t len ) + esp_err_t handleExternalWriteAtIndex(uint8_t index, const void *value, const size_t len) { if (index == 9) { /* This is only done for small-page blobs for now*/ if (len > smallBlobLen) { @@ -1354,8 +1349,8 @@ TEST_CASE("monkey test", "[nvs][monkey]") TEMPORARILY_DISABLED(f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); nvs_handle_t handle; TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); @@ -1375,8 +1370,8 @@ TEST_CASE("test for memory leaks in open/set", "[leaks]") const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; TEMPORARILY_DISABLED(f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); for (int i = 0; i < 100000; ++i) { nvs_handle_t light_handle = 0; @@ -1405,7 +1400,7 @@ TEST_CASE("read/write failure (TW8406)", "[nvs]") ESP_ERROR_CHECK(nvs_open("LIGHT", NVS_READWRITE, &light_handle)); ESP_ERROR_CHECK(nvs_set_u8(light_handle, "RecordNum", number)); for (i = 0; i < number; ++i) { - sprintf(key, "light%d", i); + snprintf(key, sizeof(key), "light%d", i); ESP_ERROR_CHECK(nvs_set_blob(light_handle, key, data, sizeof(data))); } nvs_commit(light_handle); @@ -1415,7 +1410,7 @@ TEST_CASE("read/write failure (TW8406)", "[nvs]") REQUIRE(number == get_number); for (i = 0; i < number; ++i) { char data[76] = {0}; - sprintf(key, "light%d", i); + snprintf(key, sizeof(key), "light%d", i); ESP_ERROR_CHECK(nvs_get_blob(light_handle, key, data, &data_len)); } nvs_close(light_handle); @@ -1429,22 +1424,22 @@ TEST_CASE("nvs_flash_init checks for an empty page", "[nvs]") const size_t blob_size = nvs::Page::CHUNK_MAX_SIZE; uint8_t blob[blob_size] = {0}; PartitionEmulationFixture f(0, 8); - TEST_ESP_OK( nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 5) ); + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 5)); nvs_handle_t handle; - TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &handle)); // Fill first page - TEST_ESP_OK( nvs_set_blob(handle, "1a", blob, blob_size) ); + TEST_ESP_OK(nvs_set_blob(handle, "1a", blob, blob_size)); // Fill second page - TEST_ESP_OK( nvs_set_blob(handle, "2a", blob, blob_size) ); + TEST_ESP_OK(nvs_set_blob(handle, "2a", blob, blob_size)); // Fill third page - TEST_ESP_OK( nvs_set_blob(handle, "3a", blob, blob_size) ); - TEST_ESP_OK( nvs_commit(handle) ); + TEST_ESP_OK(nvs_set_blob(handle, "3a", blob, blob_size)); + TEST_ESP_OK(nvs_commit(handle)); nvs_close(handle); TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); // first two pages are now full, third one is writable, last two are empty // init should fail - TEST_ESP_ERR( nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 3), - ESP_ERR_NVS_NO_FREE_PAGES ); + TEST_ESP_ERR(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 3), + ESP_ERR_NVS_NO_FREE_PAGES); // in case this test fails, to not affect other tests nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME); @@ -1455,19 +1450,19 @@ TEST_CASE("nvs page selection takes into account free entries also not just eras const size_t blob_size = nvs::Page::CHUNK_MAX_SIZE / 2; uint8_t blob[blob_size] = {0}; PartitionEmulationFixture f(0, 3); - TEST_ESP_OK( nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 3) ); + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 3)); nvs_handle_t handle; - TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &handle)); // Fill first page - TEST_ESP_OK( nvs_set_blob(handle, "1a", blob, blob_size / 3) ); - TEST_ESP_OK( nvs_set_blob(handle, "1b", blob, blob_size) ); + TEST_ESP_OK(nvs_set_blob(handle, "1a", blob, blob_size / 3)); + TEST_ESP_OK(nvs_set_blob(handle, "1b", blob, blob_size)); // Fill second page - TEST_ESP_OK( nvs_set_blob(handle, "2a", blob, blob_size) ); - TEST_ESP_OK( nvs_set_blob(handle, "2b", blob, blob_size) ); + TEST_ESP_OK(nvs_set_blob(handle, "2a", blob, blob_size)); + TEST_ESP_OK(nvs_set_blob(handle, "2b", blob, blob_size)); // The item below should be able to fit the first page. - TEST_ESP_OK( nvs_set_blob(handle, "3a", blob, 4) ); - TEST_ESP_OK( nvs_commit(handle) ); + TEST_ESP_OK(nvs_set_blob(handle, "3a", blob, 4)); + TEST_ESP_OK(nvs_commit(handle)); nvs_close(handle); TEST_ESP_OK(nvs_flash_deinit_partition(f.part()->get_partition_name())); @@ -1672,21 +1667,21 @@ TEST_CASE("Modification of values for Multi-page blobs are supported", "[nvs]") uint8_t blob4[blob_size] = { 0x33}; size_t read_size = blob_size; PartitionEmulationFixture f(0, 6); - TEST_ESP_OK( nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 6) ); + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 6)); nvs_handle_t handle; memset(blob, 0x11, blob_size); memset(blob2, 0x22, blob_size); memset(blob3, 0x33, blob_size); memset(blob4, 0x44, blob_size); memset(blob_read, 0xff, blob_size); - TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); - TEST_ESP_OK( nvs_set_blob(handle, "abc", blob, blob_size) ); - TEST_ESP_OK( nvs_set_blob(handle, "abc", blob2, blob_size) ); - TEST_ESP_OK( nvs_set_blob(handle, "abc", blob3, blob_size) ); - TEST_ESP_OK( nvs_set_blob(handle, "abc", blob4, blob_size) ); - TEST_ESP_OK( nvs_get_blob(handle, "abc", blob_read, &read_size)); + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &handle)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob2, blob_size)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob3, blob_size)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob4, blob_size)); + TEST_ESP_OK(nvs_get_blob(handle, "abc", blob_read, &read_size)); CHECK(memcmp(blob4, blob_read, blob_size) == 0); - TEST_ESP_OK( nvs_commit(handle) ); + TEST_ESP_OK(nvs_commit(handle)); nvs_close(handle); TEST_ESP_OK(nvs_flash_deinit_partition(f.part()->get_partition_name())); @@ -1699,14 +1694,14 @@ TEST_CASE("Modification from single page blob to multi-page", "[nvs]") uint8_t blob_read[blob_size] = {0xff}; size_t read_size = blob_size; PartitionEmulationFixture f(0, 5); - TEST_ESP_OK( nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 5) ); + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 5)); nvs_handle_t handle; - TEST_ESP_OK(nvs_open("Test", NVS_READWRITE, &handle) ); + TEST_ESP_OK(nvs_open("Test", NVS_READWRITE, &handle)); TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, nvs::Page::CHUNK_MAX_SIZE / 2)); TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); TEST_ESP_OK(nvs_get_blob(handle, "abc", blob_read, &read_size)); CHECK(memcmp(blob, blob_read, blob_size) == 0); - TEST_ESP_OK(nvs_commit(handle) ); + TEST_ESP_OK(nvs_commit(handle)); nvs_close(handle); TEST_ESP_OK(nvs_flash_deinit_partition(f.part()->get_partition_name())); @@ -1719,15 +1714,15 @@ TEST_CASE("Modification from multi-page to single page", "[nvs]") uint8_t blob_read[blob_size] = {0xff}; size_t read_size = blob_size; PartitionEmulationFixture f(0, 5); - TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 5) ); + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 5)); nvs_handle_t handle; - TEST_ESP_OK(nvs_open("Test", NVS_READWRITE, &handle) ); + TEST_ESP_OK(nvs_open("Test", NVS_READWRITE, &handle)); TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, nvs::Page::CHUNK_MAX_SIZE / 2)); TEST_ESP_OK(nvs_set_blob(handle, "abc2", blob, blob_size)); TEST_ESP_OK(nvs_get_blob(handle, "abc", blob_read, &read_size)); CHECK(memcmp(blob, blob_read, nvs::Page::CHUNK_MAX_SIZE) == 0); - TEST_ESP_OK(nvs_commit(handle) ); + TEST_ESP_OK(nvs_commit(handle)); nvs_close(handle); TEST_ESP_OK(nvs_flash_deinit_partition(f.part()->get_partition_name())); @@ -1765,7 +1760,6 @@ TEST_CASE("Check that orphaned blobs are erased during init", "[nvs]") TEST_ESP_OK(storage.writeItem(1, nvs::ItemType::BLOB, "key", blob, sizeof(blob))); - TEST_ESP_OK(storage.init(0, 5)); /* Check that multi-page item is still available.**/ TEST_ESP_OK(storage.readItem(1, nvs::ItemType::BLOB, "key", blob, sizeof(blob))); @@ -1785,21 +1779,21 @@ TEST_CASE("Check that orphaned blobs are erased during init", "[nvs]") TEST_CASE("nvs blob fragmentation test", "[nvs]") { PartitionEmulationFixture f(0, 4); - TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 4) ); + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 4)); const size_t BLOB_SIZE = 3500; uint8_t *blob = (uint8_t *) malloc(BLOB_SIZE); CHECK(blob != NULL); memset(blob, 0xEE, BLOB_SIZE); const uint32_t magic = 0xff33eaeb; nvs_handle_t h; - TEST_ESP_OK( nvs_open("blob_tests", NVS_READWRITE, &h) ); + TEST_ESP_OK(nvs_open("blob_tests", NVS_READWRITE, &h)); for (int i = 0; i < 128; i++) { INFO("Iteration " << i << "...\n"); - TEST_ESP_OK( nvs_set_u32(h, "magic", magic) ); - TEST_ESP_OK( nvs_set_blob(h, "blob", blob, BLOB_SIZE) ); + TEST_ESP_OK(nvs_set_u32(h, "magic", magic)); + TEST_ESP_OK(nvs_set_blob(h, "blob", blob, BLOB_SIZE)); char seq_buf[16]; - sprintf(seq_buf, "seq%d", i); - TEST_ESP_OK( nvs_set_u32(h, seq_buf, i) ); + snprintf(seq_buf, sizeof(seq_buf), "seq%d", i); + TEST_ESP_OK(nvs_set_u32(h, seq_buf, i)); } free(blob); @@ -1818,12 +1812,12 @@ TEST_CASE("nvs code handles errors properly when partition is near to full", "[n /* Four pages should fit roughly 12 blobs*/ for (uint8_t count = 1; count <= 12; count++) { - sprintf(nvs_key, "key:%u", count); + snprintf(nvs_key, sizeof(nvs_key), "key:%u", count); TEST_ESP_OK(storage.writeItem(1, nvs::ItemType::BLOB, nvs_key, blob, sizeof(blob))); } for (uint8_t count = 13; count <= 20; count++) { - sprintf(nvs_key, "key:%u", count); + snprintf(nvs_key, sizeof(nvs_key), "key:%u", count); TEST_ESP_ERR(storage.writeItem(1, nvs::ItemType::BLOB, nvs_key, blob, sizeof(blob)), ESP_ERR_NVS_NOT_ENOUGH_SPACE); } } @@ -1864,14 +1858,14 @@ TEST_CASE("monkey test with old-format blob present", "[nvs][monkey]") TEMPORARILY_DISABLED(f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);) TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); nvs_handle_t handle; TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); RandomTest test; - for ( uint8_t it = 0; it < 10; it++) { + for (uint8_t it = 0; it < 10; it++) { size_t count = 200; /* Erase index and chunks for the blob with "singlepage" key */ @@ -1910,8 +1904,8 @@ TEST_CASE("monkey test with old-format blob present", "[nvs][monkey]") TEST_ESP_OK(nvs_flash_deinit_partition(f.part()->get_partition_name())); /* Initialize again */ TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), - NVS_FLASH_SECTOR, - NVS_FLASH_SECTOR_COUNT_MIN)); + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); /* Perform random things */ @@ -1987,7 +1981,7 @@ TEST_CASE("Recovery from power-off during modification of blob present in old-fo TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 3)); TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); - TEST_ESP_OK( nvs_get_blob(handle, "singlepage", buf, &buflen)); + TEST_ESP_OK(nvs_get_blob(handle, "singlepage", buf, &buflen)); CHECK(memcmp(buf, hexdata, buflen) == 0); nvs::Page p2; @@ -2017,7 +2011,6 @@ TEST_CASE("Recovery from power-off during modification of blob present in old-fo size_t buflen = sizeof(hexdata); uint8_t buf[nvs::Page::CHUNK_MAX_SIZE]; - /* Power-off when blob was being written on the different page where its old version in old format * was present*/ nvs::Page p; @@ -2046,7 +2039,7 @@ TEST_CASE("Recovery from power-off during modification of blob present in old-fo TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), 0, 3)); TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); - TEST_ESP_OK( nvs_get_blob(handle, "singlepage", buf, &buflen)); + TEST_ESP_OK(nvs_get_blob(handle, "singlepage", buf, &buflen)); CHECK(memcmp(buf, hexdata, buflen) == 0); nvs::Page p3; diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 23086c30f2..2465ded216 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,16 +9,15 @@ #include #include "nvs_internal.h" -namespace nvs -{ +namespace nvs { Page::Page() : mPartition(nullptr) { } uint32_t Page::Header::calculateCrc32() { return esp_rom_crc32_le(0xffffffff, - reinterpret_cast(this) + offsetof(Header, mSeqNumber), - offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber)); + reinterpret_cast(this) + offsetof(Header, mSeqNumber), + offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber)); } esp_err_t Page::load(Partition *partition, uint32_t sectorNumber) @@ -45,7 +44,9 @@ esp_err_t Page::load(Partition *partition, uint32_t sectorNumber) const int BLOCK_SIZE = 128; uint32_t* block = new (std::nothrow) uint32_t[BLOCK_SIZE]; - if (!block) return ESP_ERR_NO_MEM; + if (!block) { + return ESP_ERR_NO_MEM; + } for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += 4 * BLOCK_SIZE) { rc = mPartition->read_raw(mBaseAddress + i, block, 4 * BLOCK_SIZE); @@ -66,7 +67,7 @@ esp_err_t Page::load(Partition *partition, uint32_t sectorNumber) } else { mState = header.mState; mSeqNumber = header.mSeqNumber; - if(header.mVersion < NVS_VERSION) { + if (header.mVersion < NVS_VERSION) { return ESP_ERR_NVS_NEW_VERSION_FOUND; } else { mVersion = header.mVersion; @@ -91,7 +92,7 @@ esp_err_t Page::load(Partition *partition, uint32_t sectorNumber) return ESP_OK; } -esp_err_t Page::writeEntry(const Item& item) +esp_err_t Page::writeEntry(const Item &item) { uint32_t phyAddr; esp_err_t err = getEntryAddress(mNextFreeEntry, &phyAddr); @@ -100,7 +101,6 @@ esp_err_t Page::writeEntry(const Item& item) } err = mPartition->write(phyAddr, &item, sizeof(item)); - if (err != ESP_OK) { mState = PageState::INVALID; return err; @@ -189,7 +189,7 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c // primitive types should fit into one entry NVS_ASSERT_OR_RETURN(totalSize == ENTRY_SIZE || - isVariableLengthType(datatype), ESP_ERR_NVS_VALUE_TOO_LONG); + isVariableLengthType(datatype), ESP_ERR_NVS_VALUE_TOO_LONG); if (mNextFreeEntry == INVALID_ENTRY || mNextFreeEntry + entriesCount > ENTRY_COUNT) { // page will not fit this amount of data @@ -282,12 +282,12 @@ esp_err_t Page::readItem(uint8_t nsIndex, ItemType datatype, const char* key, vo return rc; } size_t willCopy = ENTRY_SIZE; - willCopy = (left < willCopy)?left:willCopy; + willCopy = (left < willCopy) ? left : willCopy; memcpy(dst, ditem.rawData, willCopy); left -= willCopy; dst += willCopy; } - if (Item::calculateCrc32(reinterpret_cast(data), item.varLength.dataSize) != item.varLength.dataCrc32) { + if (Item::calculateCrc32(reinterpret_cast(data), item.varLength.dataSize) != item.varLength.dataCrc32) { rc = eraseEntryAndSpan(index); if (rc != ESP_OK) { return rc; @@ -335,14 +335,14 @@ esp_err_t Page::cmpItem(uint8_t nsIndex, ItemType datatype, const char* key, con return rc; } size_t willCopy = ENTRY_SIZE; - willCopy = (left < willCopy)?left:willCopy; + willCopy = (left < willCopy) ? left : willCopy; if (memcmp(dst, ditem.rawData, willCopy)) { return ESP_ERR_NVS_CONTENT_DIFFERS; } left -= willCopy; dst += willCopy; } - if (Item::calculateCrc32(reinterpret_cast(data), item.varLength.dataSize) != item.varLength.dataCrc32) { + if (Item::calculateCrc32(reinterpret_cast(data), item.varLength.dataSize) != item.varLength.dataCrc32) { return ESP_ERR_NVS_NOT_FOUND; } @@ -385,7 +385,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index) if (rc != ESP_OK) { return rc; } - if (item.calculateCrc32() != item.crc32) { + if (!item.checkHeaderConsistency(index)) { mHashList.erase(index); rc = alterEntryState(index, EntryState::ERASED); --mUsedEntryCount; @@ -459,7 +459,7 @@ esp_err_t Page::updateFirstUsedEntry(size_t index, size_t span) return ESP_OK; } -esp_err_t Page::copyItems(Page& other) +esp_err_t Page::copyItems(Page &other) { if (mFirstUsedEntry == INVALID_ENTRY) { return ESP_ERR_NVS_NOT_FOUND; @@ -507,7 +507,10 @@ esp_err_t Page::copyItems(Page& other) NVS_ASSERT_OR_RETURN(end <= ENTRY_COUNT, ESP_FAIL); for (size_t i = readEntryIndex + 1; i < end; ++i) { - readEntry(i, entry); + err = readEntry(i, entry); + if (err != ESP_OK) { + return err; + } err = other.writeEntry(entry); if (err != ESP_OK) { return err; @@ -526,7 +529,7 @@ esp_err_t Page::mLoadEntryTable() mState == PageState::FULL || mState == PageState::FREEING) { auto rc = mPartition->read_raw(mBaseAddress + ENTRY_TABLE_OFFSET, mEntryTable.data(), - mEntryTable.byteSize()); + mEntryTable.byteSize()); if (rc != ESP_OK) { mState = PageState::INVALID; return rc; @@ -598,8 +601,7 @@ esp_err_t Page::mLoadEntryTable() --mUsedEntryCount; } ++mErasedEntryCount; - } - else { + } else { break; } } @@ -641,7 +643,7 @@ esp_err_t Page::mLoadEntryTable() return err; } - if (item.crc32 != item.calculateCrc32()) { + if (!item.checkHeaderConsistency(i)) { err = eraseEntryAndSpan(i); if (err != ESP_OK) { mState = PageState::INVALID; @@ -721,7 +723,7 @@ esp_err_t Page::mLoadEntryTable() return err; } - if (item.crc32 != item.calculateCrc32()) { + if (!item.checkHeaderConsistency(i)) { err = eraseEntryAndSpan(i); if (err != ESP_OK) { mState = PageState::INVALID; @@ -761,7 +763,6 @@ esp_err_t Page::mLoadEntryTable() return ESP_OK; } - esp_err_t Page::initialize() { NVS_ASSERT_OR_RETURN(mState == PageState::UNINITIALIZED, ESP_FAIL); @@ -793,7 +794,7 @@ esp_err_t Page::alterEntryState(size_t index, EntryState state) size_t wordToWrite = mEntryTable.getWordIndex(index); uint32_t word = mEntryTable.data()[wordToWrite]; err = mPartition->write_raw(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast(wordToWrite) * 4, - &word, sizeof(word)); + &word, sizeof(word)); if (err != ESP_OK) { mState = PageState::INVALID; return err; @@ -809,7 +810,7 @@ esp_err_t Page::alterEntryRangeState(size_t begin, size_t end, EntryState state) esp_err_t err; for (ptrdiff_t i = end - 1; i >= static_cast(begin); --i) { err = mEntryTable.set(i, state); - if (err != ESP_OK){ + if (err != ESP_OK) { return err; } size_t nextWordIndex; @@ -821,7 +822,7 @@ esp_err_t Page::alterEntryRangeState(size_t begin, size_t end, EntryState state) if (nextWordIndex != wordIndex) { uint32_t word = mEntryTable.data()[wordIndex]; auto rc = mPartition->write_raw(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast(wordIndex) * 4, - &word, 4); + &word, 4); if (rc != ESP_OK) { return rc; } @@ -843,7 +844,7 @@ esp_err_t Page::alterPageState(PageState state) return ESP_OK; } -esp_err_t Page::readEntry(size_t index, Item& dst) const +esp_err_t Page::readEntry(size_t index, Item &dst) const { uint32_t phyAddr; esp_err_t rc = getEntryAddress(index, &phyAddr); @@ -857,7 +858,7 @@ esp_err_t Page::readEntry(size_t index, Item& dst) const return ESP_OK; } -esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item, uint8_t chunkIdx, VerOffset chunkStart) +esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item &item, uint8_t chunkIdx, VerOffset chunkStart) { if (mState == PageState::CORRUPT || mState == PageState::INVALID || mState == PageState::UNINITIALIZED) { return ESP_ERR_NVS_NOT_FOUND; @@ -909,8 +910,7 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si return rc; } - auto crc32 = item.calculateCrc32(); - if (item.crc32 != crc32) { + if (!item.checkHeaderConsistency(i)) { rc = eraseEntryAndSpan(i); if (rc != ESP_OK) { mState = PageState::INVALID; @@ -974,7 +974,6 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si continue; } - if (datatype != ItemType::ANY && item.datatype != datatype) { if (key == nullptr && nsIndex == NS_ANY && chunkIdx == CHUNK_ANY) { continue; // continue for bruteforce search on blob indices. @@ -991,7 +990,7 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si return ESP_ERR_NVS_NOT_FOUND; } -esp_err_t Page::getSeqNumber(uint32_t& seqNumber) const +esp_err_t Page::getSeqNumber(uint32_t &seqNumber) const { if (mState != PageState::UNINITIALIZED && mState != PageState::INVALID && mState != PageState::CORRUPT) { seqNumber = mSeqNumber; @@ -1000,7 +999,6 @@ esp_err_t Page::getSeqNumber(uint32_t& seqNumber) const return ESP_ERR_NVS_NOT_INITIALIZED; } - esp_err_t Page::setSeqNumber(uint32_t seqNumber) { if (mState != PageState::UNINITIALIZED) { @@ -1058,40 +1056,41 @@ size_t Page::getVarDataTailroom() const } else if (mState == PageState::FULL) { return 0; } - /* Skip one entry for blob data item precessing the data */ - return ((mNextFreeEntry < (ENTRY_COUNT-1)) ? ((ENTRY_COUNT - mNextFreeEntry - 1) * ENTRY_SIZE): 0); + /* Skip one entry for blob data item processing the data */ + return ((mNextFreeEntry < (ENTRY_COUNT - 1)) ? ((ENTRY_COUNT - mNextFreeEntry - 1) * ENTRY_SIZE) : 0); } const char* Page::pageStateToName(PageState ps) { switch (ps) { - case PageState::CORRUPT: - return "CORRUPT"; + case PageState::CORRUPT: + return "CORRUPT"; - case PageState::ACTIVE: - return "ACTIVE"; + case PageState::ACTIVE: + return "ACTIVE"; - case PageState::FREEING: - return "FREEING"; + case PageState::FREEING: + return "FREEING"; - case PageState::FULL: - return "FULL"; + case PageState::FULL: + return "FULL"; - case PageState::INVALID: - return "INVALID"; + case PageState::INVALID: + return "INVALID"; - case PageState::UNINITIALIZED: - return "UNINITIALIZED"; + case PageState::UNINITIALIZED: + return "UNINITIALIZED"; - default: - assert(0 && "invalid state value"); - return ""; + default: + assert(0 && "invalid state value"); + return ""; } } void Page::debugDump() const { - printf("state=%x (%s) addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", (uint32_t) mState, pageStateToName(mState), mBaseAddress, mSeqNumber, static_cast(mFirstUsedEntry), static_cast(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount); + printf("state=%x (%s) addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", + (uint32_t) mState, pageStateToName(mState), mBaseAddress, mSeqNumber, static_cast(mFirstUsedEntry), static_cast(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount); size_t skip = 0; for (size_t i = 0; i < ENTRY_COUNT; ++i) { printf("%3d: ", static_cast(i)); @@ -1108,7 +1107,9 @@ void Page::debugDump() const Item item; readEntry(i, item); if (skip == 0) { - printf("W ns=%2u type=%2u span=%3u key=\"%s\" chunkIdx=%d len=%d\n", item.nsIndex, static_cast(item.datatype), item.span, item.key, item.chunkIndex, (item.span != 1)?((int)item.varLength.dataSize):-1); + printf("W ns=%2u type=%2u span=%3u key=\"%s\" chunkIdx=%d len=%d\n", + item.nsIndex, static_cast(item.datatype), item.span, item.key, item.chunkIndex, (item.span != 1)?((int)item.varLength.dataSize):-1); + if (item.span > 0 && item.span <= ENTRY_COUNT - i) { skip = item.span - 1; } else { @@ -1129,24 +1130,24 @@ esp_err_t Page::calcEntries(nvs_stats_t &nvsStats) nvsStats.total_entries += ENTRY_COUNT; switch (mState) { - case PageState::UNINITIALIZED: - case PageState::CORRUPT: - nvsStats.free_entries += ENTRY_COUNT; - break; + case PageState::UNINITIALIZED: + case PageState::CORRUPT: + nvsStats.free_entries += ENTRY_COUNT; + break; - case PageState::FULL: - case PageState::ACTIVE: - nvsStats.used_entries += mUsedEntryCount; - nvsStats.free_entries += ENTRY_COUNT - mUsedEntryCount; // it's equivalent free + erase entries. - break; + case PageState::FULL: + case PageState::ACTIVE: + nvsStats.used_entries += mUsedEntryCount; + nvsStats.free_entries += ENTRY_COUNT - mUsedEntryCount; // it's equivalent free + erase entries. + break; - case PageState::INVALID: - return ESP_ERR_INVALID_STATE; - break; + case PageState::INVALID: + return ESP_ERR_INVALID_STATE; + break; - default: - assert(false && "Unhandled state"); - break; + default: + assert(false && "Unhandled state"); + break; } return ESP_OK; } diff --git a/components/nvs_flash/src/nvs_types.cpp b/components/nvs_flash/src/nvs_types.cpp index a9369a4e27..24073fc306 100644 --- a/components/nvs_flash/src/nvs_types.cpp +++ b/components/nvs_flash/src/nvs_types.cpp @@ -1,28 +1,22 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "nvs_types.hpp" - +#include "nvs_page.hpp" +#include "esp_log.h" #include "esp_rom_crc.h" -namespace nvs -{ +#define TAG "nvs" + +namespace nvs { uint32_t Item::calculateCrc32() const { uint32_t result = 0xffffffff; const uint8_t* p = reinterpret_cast(this); result = esp_rom_crc32_le(result, p + offsetof(Item, nsIndex), - offsetof(Item, crc32) - offsetof(Item, nsIndex)); + offsetof(Item, crc32) - offsetof(Item, nsIndex)); result = esp_rom_crc32_le(result, p + offsetof(Item, key), sizeof(key)); result = esp_rom_crc32_le(result, p + offsetof(Item, data), sizeof(data)); return result; @@ -33,7 +27,7 @@ uint32_t Item::calculateCrc32WithoutValue() const uint32_t result = 0xffffffff; const uint8_t* p = reinterpret_cast(this); result = esp_rom_crc32_le(result, p + offsetof(Item, nsIndex), - offsetof(Item, datatype) - offsetof(Item, nsIndex)); + offsetof(Item, datatype) - offsetof(Item, nsIndex)); result = esp_rom_crc32_le(result, p + offsetof(Item, key), sizeof(key)); result = esp_rom_crc32_le(result, p + offsetof(Item, chunkIndex), sizeof(chunkIndex)); return result; @@ -46,4 +40,114 @@ uint32_t Item::calculateCrc32(const uint8_t* data, size_t size) return result; } +bool Item::checkHeaderConsistency(const uint8_t entryIndex) const +{ + // calculate and check the crc32 + if (crc32 != calculateCrc32()) { + ESP_LOGD(TAG, "CRC32 mismatch for entry %d", entryIndex); + return false; + } + + // validate the datatype and check the rest of the header fields + switch (datatype) { + // Entries occupying just one entry + case ItemType::U8: + case ItemType::I8: + case ItemType::U16: + case ItemType::I16: + case ItemType::U32: + case ItemType::I32: + case ItemType::U64: + case ItemType::I64: { + if (span != 1) { + ESP_LOGD(TAG, "Invalid span %u for datatype %#04x", (unsigned int)span, (unsigned int)datatype); + return false; + } + break; + } + + // Special case for BLOB_IDX + case ItemType::BLOB_IDX: { + // span must be 1 + if (span != 1) { + ESP_LOGD(TAG, "Invalid span %u for BLOB_IDX", (unsigned int)span); + return false; + } + + // chunkIndex must be CHUNK_ANY + if (chunkIndex != CHUNK_ANY) { + ESP_LOGD(TAG, "Invalid chunk index %u for BLOB_IDX", (unsigned int)chunkIndex); + return false; + } + + // check maximum data length + // the maximal data length is determined by: + // maximum number of chunks. Chunks are stored in uin8_t, but are logically divided into two "VerOffset" ranges of values (0 based and 128 based) + // maximum theoretical number of entries in the chunk (Page::ENTRY_COUNT - 1) and the number of bytes entry can store (Page::ENTRY_SIZE) + const uint32_t maxDataSize = (uint32_t)((UINT8_MAX / 2) * (Page::ENTRY_COUNT - 1) * Page::ENTRY_SIZE); + if (blobIndex.dataSize > maxDataSize) { + ESP_LOGD(TAG, "Data size %u bytes exceeds maximum possible size %u bytes for BLOB_IDX", (unsigned int)blobIndex.dataSize, (unsigned int)maxDataSize); + return false; + } + break; + } + + // Entries with variable length data + case ItemType::SZ: + case ItemType::BLOB: + case ItemType::BLOB_DATA: { + uint16_t maxAvailableVDataSize; + uint8_t maxAvailablePageSpan; + uint8_t spanCalcFromLen; + + // for BLOB_DATA, chunkIndex must NOT be CHUNK_ANY as this value is used to search ALL chunks in findItem + if (datatype == ItemType::BLOB_DATA) { + // chunkIndex must not be CHUNK_ANY + if (chunkIndex == CHUNK_ANY) { + ESP_LOGD(TAG, "Invalid chunk index %u for BLOB_DATA", (unsigned int)chunkIndex); + return false; + } + } + + // variable length and span checks + + // based on the entryIndex determine the maximum variable length capacity in bytes to the end of the page + maxAvailableVDataSize = ((Page::ENTRY_COUNT - entryIndex) - 1) * Page::ENTRY_SIZE; + + // check if the variable data length is not exceeding the maximum capacity available till the end of the page + if (varLength.dataSize > maxAvailableVDataSize) { + ESP_LOGD(TAG, "Variable data length %u bytes exceeds page boundary. Maximum calculated from the current entry position within page is %u bytes for datatype %#04x ", (unsigned int)varLength.dataSize, (unsigned int)maxAvailableVDataSize, (unsigned int)datatype); + return false; + } + + // based on the entryIndex determine the maximum possible span up to the end of the page + maxAvailablePageSpan = Page::ENTRY_COUNT - entryIndex; + + // this check ensures no data is read beyond the end of the page + if (span > maxAvailablePageSpan) { + ESP_LOGD(TAG, "Span %u exceeds page boundary. Maximum calculated from the current entry position within page is %u for datatype %#04x ", (unsigned int)span, (unsigned int)maxAvailablePageSpan, (unsigned int)datatype); + return false; + } + + // here we have both span and varLength.dataSize within the page boundary. Check if these values are consistent + spanCalcFromLen = (uint8_t)(((size_t) varLength.dataSize + Page::ENTRY_SIZE - 1) / Page::ENTRY_SIZE); + spanCalcFromLen ++; // add overhead entry + + // this check ensures that the span is equal to the number of entries required to store the data plus the overhead entry + if (span != spanCalcFromLen) { + ESP_LOGD(TAG, "Span %i does not match span %u calculated from variable data length %u bytes for datatype %#04x", (unsigned int)span, (unsigned int)spanCalcFromLen, (unsigned int)varLength.dataSize, (unsigned int)datatype); + return false; + } + break; + } + + // Invalid datatype + default: { + ESP_LOGD(TAG, "Invalid datatype %#04x", (unsigned int)datatype); + return false; + } + } + return true; +} + } // namespace nvs diff --git a/components/nvs_flash/src/nvs_types.hpp b/components/nvs_flash/src/nvs_types.hpp index 53d3555693..5eda9abcd9 100644 --- a/components/nvs_flash/src/nvs_types.hpp +++ b/components/nvs_flash/src/nvs_types.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -108,6 +108,14 @@ public: dst = *reinterpret_cast(data); return ESP_OK; } + + // Returns true if item's header: + // crc32 matches the calculated crc32 + // and datatype is one of the supported types + // and span is within the allowed range for the datatype and below the maximum calculated from the entryIndex + // + // Parameter entryIndex is used to calculate the maximum span for the given entry + bool checkHeaderConsistency(const uint8_t entryIndex) const; }; } // namespace nvs diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index ad0eb8d822..f7a58a0b91 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -719,7 +719,6 @@ components/nvs_flash/src/nvs_partition.cpp components/nvs_flash/src/nvs_partition_lookup.cpp components/nvs_flash/src/nvs_partition_lookup.hpp components/nvs_flash/src/nvs_test_api.h -components/nvs_flash/src/nvs_types.cpp components/nvs_flash/src/partition.hpp components/nvs_flash/test/test_nvs.c components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp