diff --git a/components/nvs_flash/include/nvs.h b/components/nvs_flash/include/nvs.h index 8a445127cc..89f9ce81f9 100644 --- a/components/nvs_flash/include/nvs.h +++ b/components/nvs_flash/include/nvs.h @@ -62,7 +62,9 @@ typedef nvs_handle_t nvs_handle IDF_DEPRECATED("Replace with nvs_handle_t"); #define ESP_ERR_NVS_CONTENT_DIFFERS (ESP_ERR_NVS_BASE + 0x18) /*!< Internal error; never returned by nvs API functions. NVS key is different in comparison */ -#define NVS_DEFAULT_PART_NAME "nvs" /*!< Default partition name of the NVS partition in the partition table */ +#define NVS_DEFAULT_PART_NAME "nvs" /*!< Default partition name of the NVS partition in the partition table */ + +#define NVS_PART_NAME_MAX_SIZE 16 /*!< maximum length of partition name (excluding null terminator) */ /** * @brief Mode of opening the non-volatile storage diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index 55b218ec56..0f25e95ad8 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -50,8 +50,7 @@ esp_err_t nvs_flash_init(void); /** * @brief Initialize NVS flash storage for the specified partition. * - * @param[in] partition_label Label of the partition. Note that internally a reference to - * passed value is kept and it should be accessible for future operations + * @param[in] partition_label Label of the partition. Must be no longer than 16 characters. * * @return * - ESP_OK if storage was successfully initialized. @@ -118,8 +117,8 @@ esp_err_t nvs_flash_erase_partition(const char *part_name); * This API initialises the default NVS partition. The default NVS partition * is the one that is labeled "nvs" in the partition table. * - * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. - * If cfg is NULL, no encryption is used. + * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. + * If cfg is NULL, no encryption is used. * * @return * - ESP_OK if storage was successfully initialized. @@ -136,8 +135,8 @@ esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg); * @param[in] partition_label Label of the partition. Note that internally a reference to * passed value is kept and it should be accessible for future operations * - * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. - * If cfg is null, no encryption/decryption is used. + * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. + * If cfg is null, no encryption/decryption is used. * @return * - ESP_OK if storage was successfully initialized. * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages @@ -149,16 +148,16 @@ esp_err_t nvs_flash_secure_init_partition(const char *partition_label, nvs_sec_c /** * @brief Generate and store NVS keys in the provided esp partition - * + * * @param[in] partition Pointer to partition structure obtained using * esp_partition_find_first or esp_partition_get. * Must be non-NULL. * @param[out] cfg Pointer to nvs security configuration structure. - * Pointer must be non-NULL. + * Pointer must be non-NULL. * Generated keys will be populated in this structure. * * - * @return + * @return * -ESP_OK, if cfg was read successfully; * -or error codes from esp_partition_write/erase APIs. */ @@ -167,8 +166,8 @@ esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_ /** - * @brief Read NVS security configuration from a partition. - * + * @brief Read NVS security configuration from a partition. + * * @param[in] partition Pointer to partition structure obtained using * esp_partition_find_first or esp_partition_get. * Must be non-NULL. @@ -177,7 +176,7 @@ esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_ * * @note Provided parition is assumed to be marked 'encrypted'. * - * @return + * @return * -ESP_OK, if cfg was read successfully; * -ESP_ERR_NVS_KEYS_NOT_INITIALIZED, if the partition is not yet written with keys. * -ESP_ERR_NVS_CORRUPT_KEY_PART, if the partition containing keys is found to be corrupt diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index c41e6fb3f7..778bed2609 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -102,6 +102,8 @@ extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSe { ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount); + if (strlen(partName) > NVS_PART_NAME_MAX_SIZE) return ESP_ERR_INVALID_ARG; + nvs::Storage* new_storage = NULL; nvs::Storage* storage = lookup_storage_from_name(partName); if (storage == NULL) { diff --git a/components/nvs_flash/src/nvs_storage.hpp b/components/nvs_flash/src/nvs_storage.hpp index 65659bcc0c..f74100f4e6 100644 --- a/components/nvs_flash/src/nvs_storage.hpp +++ b/components/nvs_flash/src/nvs_storage.hpp @@ -15,7 +15,6 @@ #define nvs_storage_hpp #include -#include #include #include "nvs.hpp" #include "nvs_types.hpp" @@ -52,8 +51,8 @@ class Storage : public intrusive_list_node public: char key[Item::MAX_KEY_LENGTH + 1]; uint8_t nsIndex; - uint8_t chunkCount; - VerOffset chunkStart; + uint8_t chunkCount; + VerOffset chunkStart; }; typedef intrusive_list TBlobIndexList; @@ -61,7 +60,10 @@ class Storage : public intrusive_list_node public: ~Storage(); - Storage(const char *pName = NVS_DEFAULT_PART_NAME) : mPartitionName(pName) { }; + Storage(const char *pName = NVS_DEFAULT_PART_NAME) + { + strncpy(mPartitionName, pName, NVS_PART_NAME_MAX_SIZE); + }; esp_err_t init(uint32_t baseSector, uint32_t sectorCount); @@ -93,7 +95,7 @@ public: { return eraseItem(nsIndex, ItemType::ANY, key); } - + esp_err_t eraseNamespace(uint8_t nsIndex); const char *getPartName() const @@ -114,7 +116,7 @@ public: esp_err_t eraseMultiPageBlob(uint8_t nsIndex, const char* key, VerOffset chunkStart = VerOffset::VER_ANY); void debugDump(); - + void debugCheck(); esp_err_t fillStats(nvs_stats_t& nvsStats); @@ -143,7 +145,7 @@ protected: esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item, uint8_t chunkIdx = Page::CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY); protected: - const char *mPartitionName; + char mPartitionName [NVS_PART_NAME_MAX_SIZE + 1]; size_t mPageCount; PageManager mPageManager; TNamespaces mNamespaces; diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index 4b2181064e..648b6c900b 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -549,6 +549,72 @@ TEST_CASE("can erase items", "[nvs]") CHECK(storage.readItem(3, "key00222", val) == ESP_ERR_NVS_NOT_FOUND); } +TEST_CASE("partition name is deep copy", "[nvs]") +{ + SpiFlashEmulator emu(10); + char partition_name[16]; + strcpy(partition_name, "const_name"); + + nvs_handle_t handle_1; + nvs_handle_t handle_2; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(nvs_flash_init_custom(partition_name, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + + strcpy(partition_name, "just_kidding"); + + TEST_ESP_OK(nvs_open_from_partition("const_name", "test", NVS_READWRITE, &handle_1)); + CHECK(nvs_open_from_partition("just_kidding", "test", NVS_READWRITE, &handle_2) == ESP_ERR_NVS_PART_NOT_FOUND); + + nvs_close(handle_1); + nvs_close(handle_2); + + nvs_flash_deinit_partition("const_name"); + nvs_flash_deinit_partition("just_kidding"); // just in case, try not to affect other tests +} + +TEST_CASE("namespace name is deep copy", "[nvs]") +{ + SpiFlashEmulator emu(10); + char ns_name[16]; + strcpy(ns_name, "const_name"); + + nvs_handle_t handle_1; + nvs_handle_t handle_2; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + + TEST_ESP_OK(nvs_open("const_name", NVS_READWRITE, &handle_1)); + strcpy(ns_name, "just_kidding"); + + CHECK(nvs_open("just_kidding", NVS_READONLY, &handle_2) == ESP_ERR_NVS_NOT_FOUND); + + nvs_close(handle_1); + nvs_close(handle_2); + + nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME); +} + +TEST_CASE("Partition name no longer than 16 characters", "[nvs]") +{ + SpiFlashEmulator emu(10); + const char *TOO_LONG_NAME = "0123456789abcdefg"; + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + CHECK(nvs_flash_init_custom(TOO_LONG_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_ERR_INVALID_ARG); + + nvs_flash_deinit_partition(TOO_LONG_NAME); // just in case +} + TEST_CASE("readonly handle fails on writing", "[nvs]") { SpiFlashEmulator emu(10);