fix(esp_hw_support): validate esp_cpu debug helper args

Reject invalid breakpoint/watchpoint indices and validate
watchpoint size before alignment checks. This makes the APIs
match their documented contract and avoids crashing on invalid
input.

Made-with: Cursor
This commit is contained in:
Marius Vikhammer
2026-03-24 13:42:02 +08:00
parent 34b7749eda
commit 07a6ec9b6e
2 changed files with 41 additions and 28 deletions
+18 -21
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -72,10 +72,10 @@ void esp_cpu_wait_for_intr(void)
#if SOC_CPU_BREAKPOINTS_NUM > 0
esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr)
{
/*
Todo:
- Check that bp_num is in range
*/
if (bp_num < 0 || bp_num >= SOC_CPU_BREAKPOINTS_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if __XTENSA__
xt_utils_set_breakpoint(bp_num, (uint32_t)bp_addr);
#else
@@ -101,10 +101,10 @@ esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr)
esp_err_t esp_cpu_clear_breakpoint(int bp_num)
{
/*
Todo:
- Check if the bp_num is valid
*/
if (bp_num < 0 || bp_num >= SOC_CPU_BREAKPOINTS_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if __XTENSA__
xt_utils_clear_breakpoint(bp_num);
#else
@@ -126,23 +126,20 @@ esp_err_t esp_cpu_clear_breakpoint(int bp_num)
#if SOC_CPU_WATCHPOINTS_NUM > 0
esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, esp_cpu_watchpoint_trigger_t trigger)
{
/*
Todo:
- Check if the wp_num is already in use
*/
if (wp_num < 0 || wp_num >= SOC_CPU_WATCHPOINTS_NUM) {
return ESP_ERR_INVALID_ARG;
}
// Check if size is 2^n, and size is in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE]
if (size < 1 || size > SOC_CPU_WATCHPOINT_MAX_REGION_SIZE || (size & (size - 1)) != 0) {
return ESP_ERR_INVALID_ARG;
}
// Check that the watched region's start address is naturally aligned to the size of the region
if ((uint32_t)wp_addr % size) {
return ESP_ERR_INVALID_ARG;
}
// Check if size is 2^n, and size is in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE]
if (size < 1 || size > SOC_CPU_WATCHPOINT_MAX_REGION_SIZE || (size & (size - 1)) != 0) {
return ESP_ERR_INVALID_ARG;
}
bool on_read = (trigger == ESP_CPU_WATCHPOINT_LOAD || trigger == ESP_CPU_WATCHPOINT_ACCESS);
bool on_write = (trigger == ESP_CPU_WATCHPOINT_STORE || trigger == ESP_CPU_WATCHPOINT_ACCESS);
#if __XTENSA__
@@ -166,10 +163,10 @@ esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, e
esp_err_t esp_cpu_clear_watchpoint(int wp_num)
{
/*
Todo:
- Check if the wp_num is valid
*/
if (wp_num < 0 || wp_num >= SOC_CPU_WATCHPOINTS_NUM) {
return ESP_ERR_INVALID_ARG;
}
#if __XTENSA__
xt_utils_clear_watchpoint(wp_num);
#else
+23 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -110,6 +110,10 @@ void esp_cpu_reset(int core_id);
* This function causes the current CPU core to execute its Wait For Interrupt
* (WFI or equivalent) instruction. After executing this function, the CPU core
* will stop execution until an interrupt occurs.
*
* @note On some RISC-V targets, if a debugger is attached while the hardware
* wait mode is disabled, this function may return immediately instead of
* entering WFI. This keeps debugger memory access working.
*/
void esp_cpu_wait_for_intr(void);
@@ -441,12 +445,12 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_handler(int intr_num, esp_cpu_intr_handl
}
/**
* @brief Get a handler function's argument of
* @brief Get a handler function's argument
*
* Get the argument of a previously assigned handler function on the current CPU.
*
* @param intr_num Interrupt number (from 0 to 31)
* @return The the argument passed to the handler function
* @return The argument passed to the handler function
*/
FORCE_INLINE_ATTR void *esp_cpu_intr_get_handler_arg(int intr_num)
{
@@ -554,7 +558,10 @@ void esp_cpu_configure_region_protection(void);
* @note Overwrites previously set breakpoint with same breakpoint number.
* @param bp_num Hardware breakpoint number [0..SOC_CPU_BREAKPOINTS_NUM - 1]
* @param bp_addr Address to set a breakpoint on
* @return ESP_OK if breakpoint is set. Failure otherwise
* @return
* - ESP_OK if the breakpoint is set
* - ESP_ERR_INVALID_ARG if `bp_num` is out of range
* - ESP_ERR_INVALID_RESPONSE if setting the breakpoint via semihosting fails
*/
esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr);
@@ -563,7 +570,10 @@ esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr);
*
* @note Clears a breakpoint regardless of whether it was previously set
* @param bp_num Hardware breakpoint number [0..SOC_CPU_BREAKPOINTS_NUM - 1]
* @return ESP_OK if breakpoint is cleared. Failure otherwise
* @return
* - ESP_OK if the breakpoint is cleared
* - ESP_ERR_INVALID_ARG if `bp_num` is out of range
* - ESP_ERR_INVALID_RESPONSE if clearing the breakpoint via semihosting fails
*/
esp_err_t esp_cpu_clear_breakpoint(int bp_num);
@@ -587,7 +597,10 @@ esp_err_t esp_cpu_clear_breakpoint(int bp_num);
* @param wp_addr Watchpoint's base address, must be naturally aligned to the size of the region
* @param size Size of the region to watch. Must be one of 2^n and in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE]
* @param trigger Trigger type
* @return ESP_ERR_INVALID_ARG on invalid arg, ESP_OK otherwise
* @return
* - ESP_OK if the watchpoint is set
* - ESP_ERR_INVALID_ARG if `wp_num`, `wp_addr`, or `size` is invalid
* - ESP_ERR_INVALID_RESPONSE if setting the watchpoint via semihosting fails
*/
esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, esp_cpu_watchpoint_trigger_t trigger);
@@ -596,7 +609,10 @@ esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, e
*
* @note Clears a watchpoint regardless of whether it was previously set
* @param wp_num Hardware watchpoint number [0..SOC_CPU_WATCHPOINTS_NUM - 1]
* @return ESP_OK if watchpoint was cleared. Failure otherwise.
* @return
* - ESP_OK if the watchpoint is cleared
* - ESP_ERR_INVALID_ARG if `wp_num` is out of range
* - ESP_ERR_INVALID_RESPONSE if clearing the watchpoint via semihosting fails
*/
esp_err_t esp_cpu_clear_watchpoint(int wp_num);