diff --git a/components/nvs_flash/host_test/nvs_host_test/main/test_fixtures.hpp b/components/nvs_flash/host_test/nvs_host_test/main/test_fixtures.hpp index f98e136743..63b131b5f0 100644 --- a/components/nvs_flash/host_test/nvs_host_test/main/test_fixtures.hpp +++ b/components/nvs_flash/host_test/nvs_host_test/main/test_fixtures.hpp @@ -23,7 +23,8 @@ public: esp_partition.size = sector_size * SPI_FLASH_SEC_SIZE; esp_partition.erase_size = ESP_PARTITION_EMULATED_SECTOR_SIZE; strncpy(esp_partition.label, partition_name, PART_NAME_MAX_SIZE); - p_part = new nvs::NVSPartition(&esp_partition); + p_part = new (std::nothrow) nvs::NVSPartition(&esp_partition); + CHECK(p_part != nullptr); } ~PartitionEmulationFixture() diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index 6d7f546050..8d8d0b013d 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -13,6 +13,7 @@ #include "esp_partition.h" #include #include "nvs_handle_simple.hpp" +#include "nvs_memory_management.hpp" #include "esp_err.h" #include #include "nvs_internal.h" @@ -22,7 +23,7 @@ #include "esp_log.h" static const char* TAG = "nvs"; -class NVSHandleEntry : public intrusive_list_node { +class NVSHandleEntry : public intrusive_list_node, public ExceptionlessAllocatable { public: NVSHandleEntry(nvs::NVSHandleSimple *handle, const char* part_name) : nvs_handle(handle), diff --git a/components/nvs_flash/src/nvs_handle_simple.hpp b/components/nvs_flash/src/nvs_handle_simple.hpp index 0a20aa4e8f..ff0e93a3d6 100644 --- a/components/nvs_flash/src/nvs_handle_simple.hpp +++ b/components/nvs_flash/src/nvs_handle_simple.hpp @@ -1,16 +1,8 @@ -// 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-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef NVS_HANDLE_SIMPLE_HPP_ #define NVS_HANDLE_SIMPLE_HPP_ @@ -18,6 +10,7 @@ #include "nvs_storage.hpp" #include "nvs_platform.hpp" +#include "nvs_memory_management.hpp" #include "nvs_handle.hpp" namespace nvs { @@ -30,7 +23,9 @@ namespace nvs { * * For more details about the general member functions, see nvs_handle.hpp. */ -class NVSHandleSimple : public intrusive_list_node, public NVSHandle { +class NVSHandleSimple : public intrusive_list_node, + public NVSHandle, + public ExceptionlessAllocatable { friend class NVSPartitionManager; public: NVSHandleSimple(bool readOnly, uint8_t nsIndex, Storage *StoragePtr) : diff --git a/components/nvs_flash/src/nvs_item_hash_list.hpp b/components/nvs_flash/src/nvs_item_hash_list.hpp index e724c4f02f..ead5eeb10f 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.hpp +++ b/components/nvs_flash/src/nvs_item_hash_list.hpp @@ -1,22 +1,15 @@ -// 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-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef nvs_item_hash_list_h #define nvs_item_hash_list_h #include "nvs.h" #include "nvs_types.hpp" +#include "nvs_memory_management.hpp" #include "intrusive_list.h" namespace nvs @@ -54,7 +47,7 @@ protected: uint32_t mHash : 24; }; - struct HashListBlock : public intrusive_list_node { + struct HashListBlock : public intrusive_list_node, public ExceptionlessAllocatable { HashListBlock(); static const size_t BYTE_SIZE = 128; diff --git a/components/nvs_flash/src/nvs_memory_management.hpp b/components/nvs_flash/src/nvs_memory_management.hpp new file mode 100644 index 0000000000..933f08256e --- /dev/null +++ b/components/nvs_flash/src/nvs_memory_management.hpp @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#pragma once + +/** + * @brief Type that is only usable with new (std::nothrow) to avoid exceptions. + * + * This struct shall be inherited by all types in NVS that may be allocated dynamically (with new). + * + * NVS allocates memory at runtime. Because we use C++, we need to avoid the global ``operator new`` from libstdc++, + * since it throws exceptions and we compile NVS with ``-fno-exceptions``. We also need to avoid the global + * non-throwing version of that operator from libstdc++, since it is merely a wrapper around the original operator + * catching all exceptions. + * + * This struct removes the normal operator new from this and all types inheriting from it. It furthermore provides + * a custom version of operator new (..., const std::nothrow_t&) noexcept that will not use C++ exceptions. + * + * E.g., if you have a type MyType inheriting from ExceptionlessAllocatable, you want to use it as follows: + * @code{c++} + * MyType : public ExceptionlessAllocatable { + * ExceptionlessAllocatable(); + * ExceptionlessAllocatable(int param); + * }; + * // ... + * MyType *m0 = new (std::nothrow) MyType; + * MyType *m1 = new (std::nothrow) MyType(47); + * // ... + * delete m1; + * delete m0; + * @endcode + */ +struct ExceptionlessAllocatable { + /** + * Disallow use of the default new operator, all of NVS is currently tailored to not throw exceptions + */ + static void *operator new( std::size_t ) = delete; + + /** + * Simple implementation with malloc(). No exceptions are thrown if the allocation fails. + * To use this operator, your type must inherit from this class and then allocate with: + * @code{c} + * new (std::nothrow) ; // default constructor + * new (std::nothrow) (); // non-default constructor + * @endcode + */ + void *operator new (size_t size, const std::nothrow_t&) noexcept { + return std::malloc(size); + } + + /** + * Use \c delete as normal. This operator will be called automatically instead of the global one from libstdc++. + */ + void operator delete (void *obj) noexcept { + free(obj); + } +}; diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp index 1eed884d03..71888a263f 100644 --- a/components/nvs_flash/src/nvs_page.hpp +++ b/components/nvs_flash/src/nvs_page.hpp @@ -16,13 +16,14 @@ #include "compressed_enum_table.hpp" #include "intrusive_list.h" #include "nvs_item_hash_list.hpp" +#include "nvs_memory_management.hpp" #include "partition.hpp" namespace nvs { -class Page : public intrusive_list_node +class Page : public intrusive_list_node, public ExceptionlessAllocatable { public: static const uint32_t PSB_INIT = 0x1; diff --git a/components/nvs_flash/src/nvs_partition.hpp b/components/nvs_flash/src/nvs_partition.hpp index 2af3e238e3..8ed544a6b1 100644 --- a/components/nvs_flash/src/nvs_partition.hpp +++ b/components/nvs_flash/src/nvs_partition.hpp @@ -1,16 +1,8 @@ -// Copyright 2019 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: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef ESP_PARTITION_HPP_ #define ESP_PARTITION_HPP_ @@ -18,6 +10,7 @@ #include "esp_partition.h" #include "intrusive_list.h" #include "partition.hpp" +#include "nvs_memory_management.hpp" #define ESP_ENCRYPT_BLOCK_SIZE 16 @@ -31,7 +24,7 @@ namespace nvs { * It is implemented as an intrusive_list_node to easily store instances of it. NVSStorage and NVSPage take pointer * references of this class to abstract their partition operations. */ -class NVSPartition : public Partition, public intrusive_list_node { +class NVSPartition : public Partition, public intrusive_list_node, public ExceptionlessAllocatable { public: /** * Copy partition_name to mPartitionName and initialize mESPPartition. diff --git a/components/nvs_flash/src/nvs_partition_manager.hpp b/components/nvs_flash/src/nvs_partition_manager.hpp index 885787de4c..ebed1214e3 100644 --- a/components/nvs_flash/src/nvs_partition_manager.hpp +++ b/components/nvs_flash/src/nvs_partition_manager.hpp @@ -1,27 +1,20 @@ -// 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-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef NVS_PARTITION_MANAGER_HPP_ #define NVS_PARTITION_MANAGER_HPP_ #include "nvs_handle_simple.hpp" #include "nvs_storage.hpp" #include "nvs_partition.hpp" +#include "nvs_memory_management.hpp" #include "nvs_flash.h" namespace nvs { -class NVSPartitionManager { +class NVSPartitionManager : public ExceptionlessAllocatable { public: virtual ~NVSPartitionManager() { } diff --git a/components/nvs_flash/src/nvs_storage.hpp b/components/nvs_flash/src/nvs_storage.hpp index fd6eb1cc9f..c2df7dc470 100644 --- a/components/nvs_flash/src/nvs_storage.hpp +++ b/components/nvs_flash/src/nvs_storage.hpp @@ -1,25 +1,19 @@ -// 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-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef nvs_storage_hpp #define nvs_storage_hpp #include +#include #include #include "nvs.hpp" #include "nvs_types.hpp" #include "nvs_page.hpp" #include "nvs_pagemanager.hpp" +#include "nvs_memory_management.hpp" #include "partition.hpp" //extern void dumpBytes(const uint8_t* data, size_t count); @@ -27,14 +21,14 @@ namespace nvs { -class Storage : public intrusive_list_node +class Storage : public intrusive_list_node, public ExceptionlessAllocatable { enum class StorageState : uint32_t { INVALID, ACTIVE, }; - struct NamespaceEntry : public intrusive_list_node { + struct NamespaceEntry : public intrusive_list_node, public ExceptionlessAllocatable { public: char mName[Item::MAX_KEY_LENGTH + 1]; uint8_t mIndex; @@ -42,13 +36,13 @@ class Storage : public intrusive_list_node typedef intrusive_list TNamespaces; - struct UsedPageNode: public intrusive_list_node { + struct UsedPageNode: public intrusive_list_node, public ExceptionlessAllocatable { public: Page* mPage; }; typedef intrusive_list TUsedPageList; - struct BlobIndexNode: public intrusive_list_node { + struct BlobIndexNode: public intrusive_list_node, public ExceptionlessAllocatable { public: char key[Item::MAX_KEY_LENGTH + 1]; uint8_t nsIndex; diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index f057d2913b..7f6c2b696e 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -841,10 +841,11 @@ static void check_nvs_part_gen_args(SpiFlashEmulator *spi_flash_emulator, esp_part.address = 0; esp_part.size = size * SPI_FLASH_SEC_SIZE; strncpy(esp_part.label, part_name, PART_NAME_MAX_SIZE); - shared_ptr part; + unique_ptr part; if (is_encr) { - nvs::NVSEncryptedPartition *enc_part = new nvs::NVSEncryptedPartition(&esp_part); + nvs::NVSEncryptedPartition *enc_part = new (std::nothrow) nvs::NVSEncryptedPartition(&esp_part); + REQUIRE(enc_part != nullptr); TEST_ESP_OK(enc_part->init(xts_cfg)); part.reset(enc_part); } else { @@ -931,10 +932,11 @@ static void check_nvs_part_gen_args_mfg(SpiFlashEmulator *spi_flash_emulator, esp_part.address = 0; esp_part.size = size * SPI_FLASH_SEC_SIZE; strncpy(esp_part.label, part_name, PART_NAME_MAX_SIZE); - shared_ptr part; + unique_ptr part; if (is_encr) { - nvs::NVSEncryptedPartition *enc_part = new nvs::NVSEncryptedPartition(&esp_part); + nvs::NVSEncryptedPartition *enc_part = new (std::nothrow) nvs::NVSEncryptedPartition(&esp_part); + REQUIRE(enc_part != nullptr); TEST_ESP_OK(enc_part->init(xts_cfg)); part.reset(enc_part); } else { diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 3af655d041..a12c715bd9 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -801,17 +801,12 @@ components/nvs_flash/src/nvs_encrypted_partition.hpp components/nvs_flash/src/nvs_handle_locked.cpp components/nvs_flash/src/nvs_handle_locked.hpp components/nvs_flash/src/nvs_handle_simple.cpp -components/nvs_flash/src/nvs_handle_simple.hpp components/nvs_flash/src/nvs_item_hash_list.cpp -components/nvs_flash/src/nvs_item_hash_list.hpp components/nvs_flash/src/nvs_pagemanager.hpp components/nvs_flash/src/nvs_partition.cpp -components/nvs_flash/src/nvs_partition.hpp components/nvs_flash/src/nvs_partition_lookup.cpp components/nvs_flash/src/nvs_partition_lookup.hpp -components/nvs_flash/src/nvs_partition_manager.hpp components/nvs_flash/src/nvs_platform.hpp -components/nvs_flash/src/nvs_storage.hpp components/nvs_flash/src/nvs_test_api.h components/nvs_flash/src/nvs_types.cpp components/nvs_flash/src/partition.hpp