From 9f2a14562b6a0799628660b0735cab442bdc9a4d Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 30 Jun 2026 16:52:19 +0800 Subject: [PATCH] fix(csi): move csi_fsm init before resource allocation to fix err-path leak CSI_FSM_INIT is 1, but the controller struct is zero-allocated. Any failure before the former csi_fsm assignment (near the end of esp_cam_new_csi_ctlr) jumped to err: which called s_del_csi_ctlr. That function bailed out immediately because csi_fsm == 0, leaking the claimed slot, queue, bridge, DMA channel, PM lock, and backup buffer. Move csi_fsm = CSI_FSM_INIT right after a successful claim so the err: path properly tears down all allocated resources. --- components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c index ee2e753448e..acd3c5423f6 100644 --- a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c +++ b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c @@ -110,6 +110,7 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ free(ctlr); ESP_RETURN_ON_ERROR(ret, TAG, "no available csi controller"); } + ctlr->csi_fsm = CSI_FSM_INIT; ESP_LOGD(TAG, "config->queue_items: %d", config->queue_items); ctlr->trans_que = xQueueCreateWithCaps(config->queue_items, sizeof(esp_cam_ctlr_trans_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); @@ -213,7 +214,6 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ ESP_GOTO_ON_ERROR(dw_gdma_channel_register_event_callbacks(csi_dma_chan, &csi_dma_cbs, ctlr), err, TAG, "failed to register dwgdma callback"); ctlr->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; - ctlr->csi_fsm = CSI_FSM_INIT; ctlr->base.del = s_ctlr_del; ctlr->base.enable = s_csi_ctlr_enable; ctlr->base.start = s_ctlr_csi_start; @@ -258,7 +258,9 @@ esp_err_t s_del_csi_ctlr(csi_controller_t *ctlr) if (!ctlr->bk_buffer_dis) { free(ctlr->backup_buffer); } - vQueueDeleteWithCaps(ctlr->trans_que); + if (ctlr->trans_que) { + vQueueDeleteWithCaps(ctlr->trans_que); + } free(ctlr); return ESP_OK;