mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'contrib/github_pr_18817_v5.3' into 'release/v5.3'
fix(wear_levelling): guard WL_Flash::write()/read() against size==0 underflow (GitHub PR) (v5.3) See merge request espressif/esp-idf!50734
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -127,7 +127,7 @@ esp_err_t WL_Flash::init()
|
||||
WL_RESULT_CHECK(result);
|
||||
|
||||
int check_size = WL_STATE_CRC_LEN_V2;
|
||||
// Chech CRC and recover state
|
||||
// Check CRC and recover state
|
||||
uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
|
||||
uint32_t crc2 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_copy, check_size);
|
||||
|
||||
@@ -325,7 +325,7 @@ esp_err_t WL_Flash::updateV1_V2()
|
||||
// Check crc for old version and old version
|
||||
ESP_LOGV(TAG, "%s start", __func__);
|
||||
int check_size = WL_STATE_CRC_LEN_V1;
|
||||
// Chech CRC and recover state
|
||||
// Check CRC and recover state
|
||||
uint32_t crc1 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, check_size);
|
||||
wl_state_t sa_copy;
|
||||
wl_state_t *state_copy = &sa_copy;
|
||||
@@ -578,6 +578,10 @@ esp_err_t WL_Flash::write(size_t dest_addr, const void *src, size_t size)
|
||||
if (!this->initialized) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (size == 0) {
|
||||
// size==0: (size-1) unsigned underflow would OOB the caller buffer.
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGD(TAG, "%s - dest_addr= 0x%08" PRIx32 ", size= 0x%08" PRIx32 , __func__, (uint32_t) dest_addr, (uint32_t) size);
|
||||
uint32_t count = (size - 1) / this->cfg.wl_page_size;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
@@ -597,6 +601,10 @@ esp_err_t WL_Flash::read(size_t src_addr, void *dest, size_t size)
|
||||
if (!this->initialized) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (size == 0) {
|
||||
// Same size==0 guard as write(); avoid (size-1) underflow below.
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGD(TAG, "%s - src_addr= 0x%08" PRIx32 ", size= 0x%08" PRIx32 , __func__, (uint32_t) src_addr, (uint32_t) size);
|
||||
uint32_t count = (size - 1) / this->cfg.wl_page_size;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2016-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -99,6 +99,34 @@ TEST_CASE("write and read back data", "[wear_levelling]")
|
||||
free(read);
|
||||
}
|
||||
|
||||
TEST_CASE("write and read with zero size are safe no-ops", "[wear_levelling]")
|
||||
{
|
||||
esp_err_t result;
|
||||
wl_handle_t wl_handle;
|
||||
|
||||
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
|
||||
|
||||
// Mount wear-levelled partition
|
||||
result = wl_mount(partition, &wl_handle);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
// Zero-length wl_write/read must be no-ops; size==0 used to underflow (size-1) and OOB the buffer.
|
||||
uint8_t dummy = 0xAA;
|
||||
result = wl_write(wl_handle, 0, &dummy, 0);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
uint8_t read_back = 0x55;
|
||||
result = wl_read(wl_handle, 0, &read_back, 0);
|
||||
REQUIRE(result == ESP_OK);
|
||||
|
||||
// Untouched by a genuine zero-length read.
|
||||
REQUIRE(read_back == 0x55);
|
||||
|
||||
// Unmount
|
||||
result = wl_unmount(wl_handle);
|
||||
REQUIRE(result == ESP_OK);
|
||||
}
|
||||
|
||||
TEST_CASE("power down test", "[wear_levelling]")
|
||||
{
|
||||
esp_err_t result;
|
||||
@@ -279,7 +307,7 @@ void calculate_wl_state_address_info(const esp_partition_t *partition, size_t *o
|
||||
void calculate_wl_state_crc(WL_State_s *state_ptr)
|
||||
{
|
||||
int check_size = WL_STATE_CRC_LEN_V2;
|
||||
// Chech CRC and recover state
|
||||
// Check CRC and recover state
|
||||
state_ptr->crc32 = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)state_ptr, check_size);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user