diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index e993c9637..f6cf33d5e 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -105,7 +105,10 @@ extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSe nvs::Storage* new_storage = NULL; nvs::Storage* storage = lookup_storage_from_name(partName); if (storage == NULL) { - new_storage = new nvs::Storage((const char *)partName); + new_storage = new (std::nothrow) nvs::Storage((const char *)partName); + + if (!new_storage) return ESP_ERR_NO_MEM; + storage = new_storage; } @@ -127,6 +130,9 @@ extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t if(cfg) { auto encrMgr = EncrMgr::getInstance(); + + if (!encrMgr) return ESP_ERR_NO_MEM; + auto err = encrMgr->setSecurityContext(baseSector, sectorCount, cfg); if(err != ESP_OK) { return err; @@ -282,7 +288,10 @@ extern "C" esp_err_t nvs_open_from_partition(const char *part_name, const char* return err; } - HandleEntry *handle_entry = new HandleEntry(open_mode==NVS_READONLY, nsIndex, sHandle); + HandleEntry *handle_entry = new (std::nothrow) HandleEntry(open_mode==NVS_READONLY, nsIndex, sHandle); + + if (!handle_entry) return ESP_ERR_NO_MEM; + s_nvs_handles.push_back(handle_entry); *out_handle = handle_entry->mHandle; diff --git a/components/nvs_flash/src/nvs_encr.cpp b/components/nvs_flash/src/nvs_encr.cpp index 6f0b46cf9..c33a59547 100644 --- a/components/nvs_flash/src/nvs_encr.cpp +++ b/components/nvs_flash/src/nvs_encr.cpp @@ -27,8 +27,10 @@ namespace nvs { if(!isActive) { - instance = new EncrMgr(); - isActive = true; + instance = new (std::nothrow) EncrMgr(); + if (instance) { + isActive = true; + } } return instance; } @@ -62,7 +64,9 @@ namespace nvs uint8_t* eky = reinterpret_cast(cfg); - auto ctxt = new XtsCtxt(); + auto ctxt = new (std::nothrow) XtsCtxt(); + + if (!ctxt) return ESP_ERR_NO_MEM; ctxt->baseSector = baseSector; ctxt->sectorCount = sectorCount; diff --git a/components/nvs_flash/src/nvs_item_hash_list.cpp b/components/nvs_flash/src/nvs_item_hash_list.cpp index a6cfdac1e..7e1c1241a 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.cpp +++ b/components/nvs_flash/src/nvs_item_hash_list.cpp @@ -20,7 +20,7 @@ namespace nvs HashList::HashList() { } - + void HashList::clear() { for (auto it = mBlockList.begin(); it != mBlockList.end();) { @@ -30,7 +30,7 @@ void HashList::clear() delete static_cast(tmp); } } - + HashList::~HashList() { clear(); @@ -42,7 +42,7 @@ HashList::HashListBlock::HashListBlock() "cache block size calculation incorrect"); } -void HashList::insert(const Item& item, size_t index) +esp_err_t HashList::insert(const Item& item, size_t index) { const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff; // add entry to the end of last block if possible @@ -50,14 +50,19 @@ void HashList::insert(const Item& item, size_t index) auto& block = mBlockList.back(); if (block.mCount < HashListBlock::ENTRY_COUNT) { block.mNodes[block.mCount++] = HashListNode(hash_24, index); - return; + return ESP_OK; } } // if the above failed, create a new block and add entry to it - HashListBlock* newBlock = new HashListBlock; + HashListBlock* newBlock = new (std::nothrow) HashListBlock; + + if (!newBlock) return ESP_ERR_NO_MEM; + mBlockList.push_back(newBlock); newBlock->mNodes[0] = HashListNode(hash_24, index); newBlock->mCount++; + + return ESP_OK; } void HashList::erase(size_t index, bool itemShouldExist) diff --git a/components/nvs_flash/src/nvs_item_hash_list.hpp b/components/nvs_flash/src/nvs_item_hash_list.hpp index e759cd818..ca21c92c1 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.hpp +++ b/components/nvs_flash/src/nvs_item_hash_list.hpp @@ -27,16 +27,16 @@ class HashList public: HashList(); ~HashList(); - - void insert(const Item& item, size_t index); + + esp_err_t insert(const Item& item, size_t index); void erase(const size_t index, bool itemShouldExist=true); size_t find(size_t start, const Item& item); void clear(); - + private: HashList(const HashList& other); const HashList& operator= (const HashList& rhs); - + protected: struct HashListNode { diff --git a/components/nvs_flash/src/nvs_ops.cpp b/components/nvs_flash/src/nvs_ops.cpp index 1ee32befc..4dfcc9c11 100644 --- a/components/nvs_flash/src/nvs_ops.cpp +++ b/components/nvs_flash/src/nvs_ops.cpp @@ -26,6 +26,9 @@ esp_err_t nvs_flash_write(size_t destAddr, const void *srcAddr, size_t size) { if(EncrMgr::isEncrActive()) { auto encrMgr = EncrMgr::getInstance(); + + if (!encrMgr) return ESP_ERR_NO_MEM; + auto xtsCtxt = encrMgr->findXtsCtxtFromAddr(destAddr); if(xtsCtxt) { @@ -44,7 +47,7 @@ esp_err_t nvs_flash_write(size_t destAddr, const void *srcAddr, size_t size) { } esp_err_t nvs_flash_read(size_t srcAddr, void *destAddr, size_t size) { - + auto err = spi_flash_read(srcAddr, destAddr, size); if(err != ESP_OK) { @@ -53,6 +56,9 @@ esp_err_t nvs_flash_read(size_t srcAddr, void *destAddr, size_t size) { if(EncrMgr::isEncrActive()) { auto encrMgr = EncrMgr::getInstance(); + + if (!encrMgr) return ESP_ERR_NO_MEM; + auto xtsCtxt = encrMgr->findXtsCtxtFromAddr(srcAddr); if(xtsCtxt) { return encrMgr->decryptNvsData(static_cast(destAddr), diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index e0bda34c5..821668c18 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -49,7 +49,10 @@ esp_err_t Page::load(uint32_t sectorNumber) // check if the whole page is really empty // reading the whole page takes ~40 times less than erasing it const int BLOCK_SIZE = 128; - uint32_t* block = new uint32_t[BLOCK_SIZE]; + uint32_t* block = new (std::nothrow) uint32_t[BLOCK_SIZE]; + + if (!block) return ESP_ERR_NO_MEM; + for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += 4 * BLOCK_SIZE) { rc = spi_flash_read(mBaseAddress + i, block, 4 * BLOCK_SIZE); if (rc != ESP_OK) { @@ -215,7 +218,11 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c // write first item size_t span = (totalSize + ENTRY_SIZE - 1) / ENTRY_SIZE; item = Item(nsIndex, datatype, span, key, chunkIdx); - mHashList.insert(item, mNextFreeEntry); + err = mHashList.insert(item, mNextFreeEntry); + + if (err != ESP_OK) { + return err; + } if (!isVariableLengthType(datatype)) { memcpy(item.data, data, dataSize); @@ -426,7 +433,11 @@ esp_err_t Page::copyItems(Page& other) return err; } - other.mHashList.insert(entry, other.mNextFreeEntry); + err = other.mHashList.insert(entry, other.mNextFreeEntry); + if (err != ESP_OK) { + return err; + } + err = other.writeEntry(entry); if (err != ESP_OK) { return err; @@ -549,7 +560,11 @@ esp_err_t Page::mLoadEntryTable() continue; } - mHashList.insert(item, i); + err = mHashList.insert(item, i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } // search for potential duplicate item size_t duplicateIndex = mHashList.find(0, item); @@ -619,7 +634,11 @@ esp_err_t Page::mLoadEntryTable() assert(item.span > 0); - mHashList.insert(item, i); + err = mHashList.insert(item, i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } size_t span = item.span; diff --git a/components/nvs_flash/src/nvs_pagemanager.cpp b/components/nvs_flash/src/nvs_pagemanager.cpp index 58d9e47f4..f33a24e97 100644 --- a/components/nvs_flash/src/nvs_pagemanager.cpp +++ b/components/nvs_flash/src/nvs_pagemanager.cpp @@ -21,7 +21,9 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) mPageCount = sectorCount; mPageList.clear(); mFreePageList.clear(); - mPages.reset(new Page[sectorCount]); + mPages.reset(new (std::nothrow) Page[sectorCount]); + + if (!mPages) return ESP_ERR_NO_MEM; for (uint32_t i = 0; i < sectorCount; ++i) { auto err = mPages[i].load(baseSector + i); @@ -85,7 +87,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) break; } } - } + } } // check if power went out while page was being freed diff --git a/components/nvs_flash/src/nvs_storage.cpp b/components/nvs_flash/src/nvs_storage.cpp index be92da072..7eae18feb 100644 --- a/components/nvs_flash/src/nvs_storage.cpp +++ b/components/nvs_flash/src/nvs_storage.cpp @@ -31,7 +31,7 @@ void Storage::clearNamespaces() mNamespaces.clearAndFreeNodes(); } -void Storage::populateBlobIndices(TBlobIndexList& blobIdxList) +esp_err_t Storage::populateBlobIndices(TBlobIndexList& blobIdxList) { for (auto it = mPageManager.begin(); it != mPageManager.end(); ++it) { Page& p = *it; @@ -43,7 +43,9 @@ void Storage::populateBlobIndices(TBlobIndexList& blobIdxList) * duplicate index at this point */ while (p.findItem(Page::NS_ANY, ItemType::BLOB_IDX, nullptr, itemIndex, item) == ESP_OK) { - BlobIndexNode* entry = new BlobIndexNode; + BlobIndexNode* entry = new (std::nothrow) BlobIndexNode; + + if (!entry) return ESP_ERR_NO_MEM; item.getKey(entry->key, sizeof(entry->key) - 1); entry->nsIndex = item.nsIndex; @@ -54,6 +56,8 @@ void Storage::populateBlobIndices(TBlobIndexList& blobIdxList) itemIndex += item.span; } } + + return ESP_OK; } void Storage::eraseOrphanDataBlobs(TBlobIndexList& blobIdxList) @@ -100,7 +104,13 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount) size_t itemIndex = 0; Item item; while (p.findItem(Page::NS_INDEX, ItemType::U8, nullptr, itemIndex, item) == ESP_OK) { - NamespaceEntry* entry = new NamespaceEntry; + NamespaceEntry* entry = new (std::nothrow) NamespaceEntry; + + if (!entry) { + mState = StorageState::INVALID; + return ESP_ERR_NO_MEM; + } + item.getKey(entry->mName, sizeof(entry->mName) - 1); item.getValue(entry->mIndex); mNamespaces.push_back(entry); @@ -114,7 +124,11 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount) // Populate list of multi-page index entries. TBlobIndexList blobIdxList; - populateBlobIndices(blobIdxList); + err = populateBlobIndices(blobIdxList); + if (err != ESP_OK) { + mState = StorageState::INVALID; + return ESP_ERR_NO_MEM; + } // Remove the entries for which there is no parent multi-page index. eraseOrphanDataBlobs(blobIdxList); @@ -182,7 +196,7 @@ esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const vo return err; } else if(getCurrentPage().getVarDataTailroom() == tailroom) { /* We got the same page or we are not improving.*/ - return ESP_ERR_NVS_NOT_ENOUGH_SPACE; + return ESP_ERR_NVS_NOT_ENOUGH_SPACE; } else { continue; } @@ -203,7 +217,11 @@ esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const vo if (err != ESP_OK) { break; } else { - UsedPageNode* node = new UsedPageNode(); + UsedPageNode* node = new (std::nothrow) UsedPageNode(); + if (!node) { + err = ESP_ERR_NO_MEM; + break; + } node->mPage = &page; usedPages.push_back(node); if (remainingSize || (tailroom - chunkSize) < Page::ENTRY_SIZE) { @@ -301,9 +319,9 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key if (err != ESP_OK) { return err; } - + findPage = nullptr; - } else { + } else { /* Support for earlier versions where BLOBS were stored without index */ err = findItem(nsIndex, datatype, key, findPage, item); if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { @@ -381,6 +399,11 @@ esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uin return ESP_ERR_NVS_NOT_ENOUGH_SPACE; } + NamespaceEntry* entry = new (std::nothrow) NamespaceEntry; + if (!entry) { + return ESP_ERR_NO_MEM; + } + auto err = writeItem(Page::NS_INDEX, ItemType::U8, nsName, &ns, sizeof(ns)); if (err != ESP_OK) { return err; @@ -388,7 +411,6 @@ esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uin mNamespaceUsage.set(ns, true); nsIndex = ns; - NamespaceEntry* entry = new NamespaceEntry; entry->mIndex = ns; strncpy(entry->mName, nsName, sizeof(entry->mName) - 1); entry->mName[sizeof(entry->mName) - 1] = 0; @@ -456,14 +478,14 @@ esp_err_t Storage::readItem(uint8_t nsIndex, ItemType datatype, const char* key, if (err != ESP_ERR_NVS_NOT_FOUND) { return err; } // else check if the blob is stored with earlier version format without index - } + } auto err = findItem(nsIndex, datatype, key, findPage, item); if (err != ESP_OK) { return err; } return findPage->readItem(nsIndex, datatype, key, data, dataSize); - + } esp_err_t Storage::eraseMultiPageBlob(uint8_t nsIndex, const char* key, VerOffset chunkStart) diff --git a/components/nvs_flash/src/nvs_storage.hpp b/components/nvs_flash/src/nvs_storage.hpp index 3a79e705c..add5cca7c 100644 --- a/components/nvs_flash/src/nvs_storage.hpp +++ b/components/nvs_flash/src/nvs_storage.hpp @@ -128,7 +128,7 @@ protected: void clearNamespaces(); - void populateBlobIndices(TBlobIndexList&); + esp_err_t populateBlobIndices(TBlobIndexList&); void eraseOrphanDataBlobs(TBlobIndexList&);