Merge branch 'contrib/github_pr_18817_v6.0' into 'release/v6.0'

fix(wear_levelling): guard WL_Flash::write()/read() against size==0 underflow (GitHub PR) (v6.0)

See merge request espressif/esp-idf!50731
This commit is contained in:
Jiang Jiang Jian
2026-07-20 10:36:48 +08:00
2 changed files with 36 additions and 0 deletions
+8
View File
@@ -577,6 +577,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++) {
@@ -596,6 +600,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++) {
@@ -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;