Skip to content

Wrong usage of MBED_ASSERT cause malfunctions in Release builds #598

Description

@JohnK1987

Based on finding durring #596 I let AI agent analyze whole mbed-os for this wrong usage and found 12 issues with MBED_ASSERT. For example STM32WL will probably not work in Release profile because RCC config is placed inside MBED_ASSERT.

MBED_ASSERT expands to ((void)0) when NDEBUG is defined, so its argument is not evaluated. Several places call functions with required side effects directly inside MBED_ASSERT, causing initialization, configuration, buffer modification, or cleanup operations to be skipped in Release builds.

These function calls should be executed separately, with only their return values passed to MBED_ASSERT.

Confirmed MBED_ASSERT side-effect issues

1. GATT characteristic handle lookup is skipped

  • File: connectivity/FEATURE_BLE/source/cordio/source/GattServerImpl.cpp
  • Function: ble::impl::GattServer::handleEvent()
  • Exact lines: 1759 and 1776
  • Affected subsystem/target: Cordio BLE GATT server
  • GitHub permalinks: updates enabled, line 1759, updates disabled, line 1776
  • Assert expression:
    MBED_ASSERT(get_value_handle_by_cccd_handle(attributeHandle, charHandle));
    This expression occurs at both locations.
  • Required operation: get_value_handle_by_cccd_handle() looks up the CCCD and writes the corresponding characteristic value handle through the charHandle reference. Its implementation assigns char_handle = cccd_handles[idx].
  • Behaviour with NDEBUG: The lookup and output assignment do not happen. The subsequently constructed GattUpdatesEnabledCallbackParams or GattUpdatesDisabledCallbackParams contains an uninitialized charHandle.
  • Confidence: High

2. lwIP pbuf header adjustment is skipped

  • File: connectivity/lwipstack/source/LWIPMemoryManager.cpp
  • Function: LWIPMemoryManager::skip_header_space()
  • Exact line: 131
  • Affected subsystem/target: lwIP network buffer management
  • GitHub permalink: line 131
  • Assert expression:
    MBED_ASSERT(pbuf_header_force(static_cast<struct pbuf *>(buf), -amount) == 0);
  • Required operation: pbuf_header_force() calls pbuf_header_impl(). For the negative argument used here, it calls pbuf_remove_header(), which advances p->payload and updates p->len, p->tot_len, and p->header_bytes_removed.
  • Behaviour with NDEBUG: skip_header_space() performs no header adjustment. Buffer payload position and length metadata remain unchanged.
  • Confidence: High

3. Apollo3 BLE controller power-up is skipped

  • File: connectivity/drivers/ble/FEATURE_BLE/TARGET_Ambiq_Micro/TARGET_Apollo3/AP3CordioHCIDriver.cpp
  • Function: ble::AP3CordioHCIDriver::do_initialize()
  • Exact line: 56
  • Affected subsystem/target: Cordio BLE, Ambiq Micro Apollo3 when USE_AMBIQ_DRIVER is not defined
  • GitHub permalink: line 56
  • Assert expression:
    MBED_ASSERT(am_hal_ble_power_control(*_ptr_to_handle, AM_HAL_BLE_POWER_ACTIVE) == AM_HAL_STATUS_SUCCESS);
  • Required operation: am_hal_ble_power_control() enables the BLE power domain, releases reset, enables clocks, starts the BLE power-state machine, and waits for the controller to become active.
  • Behaviour with NDEBUG: The BLE controller is not powered or released from reset before later initialization and interrupt enablement.
  • Confidence: High

4. Apollo3 BLE hardware configuration is skipped

  • File: connectivity/drivers/ble/FEATURE_BLE/TARGET_Ambiq_Micro/TARGET_Apollo3/AP3CordioHCIDriver.cpp
  • Function: ble::AP3CordioHCIDriver::do_initialize()
  • Exact line: 57
  • Affected subsystem/target: Cordio BLE, Ambiq Micro Apollo3 when USE_AMBIQ_DRIVER is not defined
  • GitHub permalink: line 57
  • Assert expression:
    MBED_ASSERT(am_hal_ble_config(*_ptr_to_handle, &_ble_config) == AM_HAL_STATUS_SUCCESS);
  • Required operation: am_hal_ble_config() programs BLEIF SPI, FIFO, and clock registers, updates NVDS configuration where applicable, recalculates its CRC, and records patch configuration.
  • Behaviour with NDEBUG: The BLE interface and controller configuration are not applied.
  • Confidence: High

5. Apollo3 BLE boot and patch application is skipped

  • File: connectivity/drivers/ble/FEATURE_BLE/TARGET_Ambiq_Micro/TARGET_Apollo3/AP3CordioHCIDriver.cpp
  • Function: ble::AP3CordioHCIDriver::do_initialize()
  • Exact line: 58
  • Affected subsystem/target: Cordio BLE, Ambiq Micro Apollo3 when USE_AMBIQ_DRIVER is not defined
  • GitHub permalink: line 58
  • Assert expression:
    MBED_ASSERT(am_hal_ble_boot(*_ptr_to_handle) == AM_HAL_STATUS_SUCCESS);
  • Required operation: am_hal_ble_boot() performs the operations needed to prepare the BLE controller for HCI, including applicable code, trim, and NVDS patching and patch completion.
  • Behaviour with NDEBUG: Controller boot preparation and required silicon patch application do not occur.
  • Confidence: High

6. Apollo3 BLE transmit-power configuration is skipped

  • File: connectivity/drivers/ble/FEATURE_BLE/TARGET_Ambiq_Micro/TARGET_Apollo3/AP3CordioHCIDriver.cpp
  • Function: ble::AP3CordioHCIDriver::do_initialize()
  • Exact line: 59
  • Affected subsystem/target: Cordio BLE, Ambiq Micro Apollo3 when USE_AMBIQ_DRIVER is not defined
  • GitHub permalink: line 59
  • Assert expression:
    MBED_ASSERT(am_hal_ble_tx_power_set(*_ptr_to_handle, 0x0F) == AM_HAL_STATUS_SUCCESS);
  • Required operation: am_hal_ble_tx_power_set() unlocks BLE registers and writes the requested transmit-power level to controller registers/RAM.
  • Behaviour with NDEBUG: The requested 0x0F transmit-power setting is not programmed.
  • Confidence: High

7. Apollo3 BLE sleep configuration is skipped

  • File: connectivity/drivers/ble/FEATURE_BLE/TARGET_Ambiq_Micro/TARGET_Apollo3/AP3CordioHCIDriver.cpp
  • Function: ble::AP3CordioHCIDriver::do_initialize()
  • Exact line: 60
  • Affected subsystem/target: Cordio BLE, Ambiq Micro Apollo3 when USE_AMBIQ_DRIVER is not defined
  • GitHub permalink: line 60
  • Assert expression:
    MBED_ASSERT(am_hal_ble_sleep_set(*_ptr_to_handle, false) == AM_HAL_STATUS_SUCCESS);
  • Required operation: am_hal_ble_sleep_set() updates the BLE controller’s sleep-enable state in controller RAM; here it disables sleep.
  • Behaviour with NDEBUG: Sleep is not explicitly disabled during controller initialization.
  • Confidence: High

8. MAX32620C ADC initialization is skipped

  • File: targets/TARGET_Maxim/TARGET_MAX32620C/analogin_api.c
  • Function: analogin_init()
  • Exact line: 56
  • Affected subsystem/target: Analog input, Maxim MAX32620C
  • GitHub permalink: line 56
  • Assert expression:
    MBED_ASSERT(ADC_Init() == E_NO_ERROR);
  • Required operation: ADC_Init() initializes the ADC system clock/power through SYS_ADC_Init(), clears prior configuration and interrupt flags, enables the completion interrupt, and powers up the ADC and associated clock/buffer/reference circuitry.
  • Behaviour with NDEBUG: initialized is set to 1, but the ADC hardware has not actually been initialized or powered up. Later calls will also skip initialization.
  • Confidence: High

9. MAX32625 ADC initialization is skipped

  • File: targets/TARGET_Maxim/TARGET_MAX32625/analogin_api.c
  • Function: analogin_init()
  • Exact line: 56
  • Affected subsystem/target: Analog input, Maxim MAX32625
  • GitHub permalink: line 56
  • Assert expression:
    MBED_ASSERT(ADC_Init() == E_NO_ERROR);
  • Required operation: ADC_Init() enables the ADC through SYS_ADC_Init(), clears/configures ADC interrupt state, and powers up the ADC, clock, input buffer, reference buffer, and charge pump.
  • Behaviour with NDEBUG: Software marks the ADC initialized without performing the hardware initialization.
  • Confidence: High

10. MAX32630 ADC initialization is skipped

  • File: targets/TARGET_Maxim/TARGET_MAX32630/analogin_api.c
  • Function: analogin_init()
  • Exact line: 56
  • Affected subsystem/target: Analog input, Maxim MAX32630
  • GitHub permalink: line 56
  • Assert expression:
    MBED_ASSERT(ADC_Init() == E_NO_ERROR);
  • Required operation: ADC_Init() enables the ADC through SYS_ADC_Init(), clears/configures ADC interrupt state, and powers up the ADC, clock, input buffer, reference buffer, and charge pump.
  • Behaviour with NDEBUG: Software marks the ADC initialized without performing the hardware initialization.
  • Confidence: High

11. STM32WL oscillator configuration is skipped

  • File: targets/TARGET_STM/TARGET_STM32WL/system_clock.c
  • Function: SetSysClock()
  • Exact line: 56
  • Affected subsystem/target: System clock initialization, STM32WL
  • GitHub permalink: line 56
  • Assert expression:
    MBED_ASSERT(HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK);
  • Required operation: STM32 HAL HAL_RCC_OscConfig() programs and starts the selected MSI oscillator configuration.
  • Behaviour with NDEBUG: The requested MSI oscillator state, calibration, and clock range are not applied.
  • Confidence: High

12. STM32WL bus and system-clock configuration is skipped

  • File: targets/TARGET_STM/TARGET_STM32WL/system_clock.c
  • Function: SetSysClock()
  • Exact line: 67
  • Affected subsystem/target: System clock initialization, STM32WL
  • GitHub permalink: line 67
  • Assert expression:
    MBED_ASSERT(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) == HAL_OK);
  • Required operation: STM32 HAL HAL_RCC_ClockConfig() applies the system-clock source, AHB/APB dividers, and flash latency.
  • Behaviour with NDEBUG: The configured MSI system-clock selection, bus dividers, and flash latency are not applied.
  • Confidence: High

Uncertain candidates

None. Other call-bearing assertions found by the audit were getters, validators, ownership/state queries, alignment checks, pin/property lookups, or equivalent read-only operations.

Audit summary

  • Inspected commit: 1f5bc495dad0d551ff12a037d7f49e8f45ed2c7f
  • Repository availability: The commit is present in mbed-ce/mbed-os and is contained by origin/main.
  • Number of MBED_ASSERT occurrences searched: 2,402 invocations, excluding 3 macro definitions
  • Number of source files searched: 14,441 tracked C/C++ source and header files
  • Number of confirmed issues: 13 assertion occurrences, grouped into 12 findings above because the identical GATT error occurs in two event branches
  • Number of uncertain candidates: 0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions