From 50b715d93fd014a49a671be08f13bacaa797977e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Tue, 21 Jul 2026 14:03:21 +0200 Subject: [PATCH] fix(sdmmc): BDL calculate sectors cast fix Closes https://github.com/espressif/esp-idf/issues/18875 --- .../include/esp_private/sdmmc_blockdev.h | 22 +++++++++++++ components/sdmmc/sdmmc_blockdev.c | 33 ++++++++++--------- .../sdmmc/test_apps/main/test_sdmmc_app.c | 26 +++++++++++++++ 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 components/sdmmc/include/esp_private/sdmmc_blockdev.h diff --git a/components/sdmmc/include/esp_private/sdmmc_blockdev.h b/components/sdmmc/include/esp_private/sdmmc_blockdev.h new file mode 100644 index 00000000000..37930d544ca --- /dev/null +++ b/components/sdmmc/include/esp_private/sdmmc_blockdev.h @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t sdmmc_blockdev_calculate_sectors(size_t sector_size, uint64_t addr, size_t data_len, + size_t *out_start_sector_num, size_t *out_num_of_sectors); + +#ifdef __cplusplus +} +#endif diff --git a/components/sdmmc/sdmmc_blockdev.c b/components/sdmmc/sdmmc_blockdev.c index d951dd6a75e..3fbf43c1b3b 100644 --- a/components/sdmmc/sdmmc_blockdev.c +++ b/components/sdmmc/sdmmc_blockdev.c @@ -1,34 +1,37 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include "esp_private/sdmmc_common.h" +#include "esp_private/sdmmc_blockdev.h" #include "esp_blockdev.h" #include "sdmmc_cmd.h" -static esp_err_t calculate_start_sector_num_and_sector_count(size_t sector_size, uint64_t addr, size_t data_len, size_t* out_start_sector_num, size_t* out_num_of_sectors) +esp_err_t sdmmc_blockdev_calculate_sectors(size_t sector_size, uint64_t addr, size_t data_len, + size_t *out_start_sector_num, size_t *out_num_of_sectors) { - size_t offset_in_start_sector = (size_t) addr % sector_size; - size_t offset_in_end_sector = (size_t) data_len % sector_size; - - // Has to be aligned to sector boundaries - if (offset_in_start_sector != 0 || offset_in_end_sector != 0) { + if (sector_size == 0 || addr % sector_size != 0 || data_len % sector_size != 0) { return ESP_ERR_INVALID_ARG; } + if (data_len > UINT64_MAX - addr) { + return ESP_ERR_INVALID_SIZE; + } - size_t start_sector_num = (size_t) addr / sector_size; - size_t last_byte_addr = (size_t) (addr + data_len - 1); // Address of the last accessed byte - size_t end_sector_num = last_byte_addr / sector_size; + uint64_t start_sector_num = addr / sector_size; + size_t num_of_sectors = data_len / sector_size; + if (start_sector_num > SIZE_MAX || num_of_sectors > SIZE_MAX - start_sector_num) { + return ESP_ERR_INVALID_SIZE; + } if (out_start_sector_num) { - *out_start_sector_num = start_sector_num; + *out_start_sector_num = (size_t) start_sector_num; } if (out_num_of_sectors) { - *out_num_of_sectors = end_sector_num - start_sector_num + 1; + *out_num_of_sectors = num_of_sectors; } return ESP_OK; @@ -41,7 +44,7 @@ static esp_err_t sdmmc_blockdev_read(esp_blockdev_handle_t handle, uint8_t* dst_ } sdmmc_card_t* card = (sdmmc_card_t*) handle->ctx; size_t start_sector_num, num_of_sectors; - esp_err_t err = calculate_start_sector_num_and_sector_count((size_t) card->csd.sector_size, src_addr, data_read_len, &start_sector_num, &num_of_sectors); + esp_err_t err = sdmmc_blockdev_calculate_sectors((size_t) card->csd.sector_size, src_addr, data_read_len, &start_sector_num, &num_of_sectors); if (err != ESP_OK) { return err; } @@ -56,7 +59,7 @@ static esp_err_t sdmmc_blockdev_write(esp_blockdev_handle_t handle, const uint8_ } sdmmc_card_t* card = (sdmmc_card_t*) handle->ctx; size_t start_sector_num, num_of_sectors; - esp_err_t err = calculate_start_sector_num_and_sector_count((size_t) card->csd.sector_size, dst_addr, data_write_len, &start_sector_num, &num_of_sectors); + esp_err_t err = sdmmc_blockdev_calculate_sectors((size_t) card->csd.sector_size, dst_addr, data_write_len, &start_sector_num, &num_of_sectors); if (err != ESP_OK) { return err; } @@ -71,7 +74,7 @@ static esp_err_t sdmmc_blockdev_erase(esp_blockdev_handle_t handle, uint64_t sta } sdmmc_card_t* card = (sdmmc_card_t*) handle->ctx; size_t start_sector_num, num_of_sectors; - esp_err_t err = calculate_start_sector_num_and_sector_count((size_t) card->csd.sector_size, start_addr, erase_len, &start_sector_num, &num_of_sectors); + esp_err_t err = sdmmc_blockdev_calculate_sectors((size_t) card->csd.sector_size, start_addr, erase_len, &start_sector_num, &num_of_sectors); if (err != ESP_OK) { return err; } diff --git a/components/sdmmc/test_apps/main/test_sdmmc_app.c b/components/sdmmc/test_apps/main/test_sdmmc_app.c index 3b45429dd88..3dee78e0621 100644 --- a/components/sdmmc/test_apps/main/test_sdmmc_app.c +++ b/components/sdmmc/test_apps/main/test_sdmmc_app.c @@ -15,9 +15,35 @@ #include "sdmmc_test_begin_end_sd.h" #include "sdmmc_test_rw_common.h" #include "esp_blockdev.h" +#include "esp_private/sdmmc_blockdev.h" #define TEST_MEMORY_LEAK_THRESHOLD (200) +TEST_CASE("sdmmc blockdev converts byte ranges to sectors", "[sdmmc]") +{ + size_t start_sector; + size_t sector_count; + + TEST_ESP_OK(sdmmc_blockdev_calculate_sectors(512, UINT64_C(0x100000000), 1024, + &start_sector, §or_count)); + TEST_ASSERT_EQUAL_UINT32(8388608, start_sector); + TEST_ASSERT_EQUAL_UINT32(2, sector_count); + + TEST_ESP_OK(sdmmc_blockdev_calculate_sectors(512, UINT64_C(0x100000000), 0, + &start_sector, §or_count)); + TEST_ASSERT_EQUAL_UINT32(8388608, start_sector); + TEST_ASSERT_EQUAL_UINT32(0, sector_count); + + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, + sdmmc_blockdev_calculate_sectors(512, 1, 512, NULL, NULL)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, + sdmmc_blockdev_calculate_sectors(512, 0, 1, NULL, NULL)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, + sdmmc_blockdev_calculate_sectors(0, 0, 512, NULL, NULL)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, + sdmmc_blockdev_calculate_sectors(512, UINT64_MAX - 511, 512, NULL, NULL)); +} + TEST_CASE("sdmmc extra, bdl interface test", "[sdcard]") { sdmmc_card_t card;