Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions components/lcd/esp_lcd_st7796/esp_lcd_st7796_general.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ static esp_err_t panel_st7796_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool
static esp_err_t panel_st7796_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
static esp_err_t panel_st7796_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
static esp_err_t panel_st7796_disp_on_off(esp_lcd_panel_t *panel, bool off);
static esp_err_t panel_st7796_disp_sleep(esp_lcd_panel_t *panel, bool sleep);

typedef struct {
esp_lcd_panel_t base;
Expand Down Expand Up @@ -141,6 +142,8 @@ esp_err_t esp_lcd_new_panel_st7796_general(const esp_lcd_panel_io_handle_t io,
#else
st7796->base.disp_on_off = panel_st7796_disp_on_off;
#endif
st7796->base.disp_sleep = panel_st7796_disp_sleep;
Comment thread
AndreaGreco marked this conversation as resolved.

*ret_panel = &(st7796->base);
ESP_LOGD(TAG, "new st7796 panel @%p", st7796);

Expand Down Expand Up @@ -369,3 +372,23 @@ static esp_err_t panel_st7796_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
return ESP_OK;
}

static esp_err_t panel_st7796_disp_sleep(esp_lcd_panel_t *panel, bool sleep)
{
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
esp_lcd_panel_io_handle_t io = st7796->io;
int command;

if (sleep) {
command = LCD_CMD_SLPIN;
} else {
command = LCD_CMD_SLPOUT;
}

ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
Comment thread
AndreaGreco marked this conversation as resolved.

/* According to the ST7796 datasheet, a delay of at least 120ms is required after sleep in/out commands */
vTaskDelay(pdMS_TO_TICKS(120));

return ESP_OK;
}
Comment thread
cursor[bot] marked this conversation as resolved.
20 changes: 20 additions & 0 deletions components/lcd/esp_lcd_st7796/esp_lcd_st7796_mipi.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ esp_err_t esp_lcd_new_panel_st7796_mipi(const esp_lcd_panel_io_handle_t io,
panel_handle->mirror = panel_st7796_mirror;
panel_handle->invert_color = panel_st7796_invert_color;
panel_handle->disp_on_off = panel_st7796_disp_on_off;
panel_handle->disp_sleep = panel_st7796_disp_sleep;
panel_handle->user_data = st7796;
*ret_panel = panel_handle;
ESP_LOGD(TAG, "new st7796 panel @%p", st7796);
Expand Down Expand Up @@ -323,4 +324,23 @@ static esp_err_t panel_st7796_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
return ESP_OK;
}

static esp_err_t panel_st7796_disp_sleep(esp_lcd_panel_t *panel, bool sleep)
{
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong struct access pattern causes undefined behavior

High Severity

The panel_st7796_disp_sleep function in the MIPI file uses __containerof(panel, st7796_panel_t, base) to access the panel structure, but the MIPI version's st7796_panel_t struct doesn't have a base member. All other functions in this file correctly use (st7796_panel_t *)panel->user_data instead. Using __containerof with a non-existent member will result in undefined behavior and likely memory corruption or crash when the function is called.

Fix in Cursor Fix in Web

Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect use of __containerof. The st7796_panel_t struct in this file does not have a 'base' member. The correct way to retrieve the st7796 pointer is: (st7796_panel_t *)panel->user_data, as used in all other functions in this file (see lines 315, 270, 287, 250). The __containerof pattern is only correct in the general variant where st7796_panel_t has 'esp_lcd_panel_t base' as its first member.

Suggested change
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
st7796_panel_t *st7796 = (st7796_panel_t *)panel->user_data;

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AndreaGreco Please, could you apply this suggestion?

esp_lcd_panel_io_handle_t io = st7796->io;
int command;

if (sleep) {
command = LCD_CMD_SLPIN;
} else {
command = LCD_CMD_SLPOUT;
}
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");

/* According to the ST7796 datasheet, a delay of at least 120ms is required after sleep in/out commands */
vTaskDelay(pdMS_TO_TICKS(120));
return ESP_OK;
}
Comment thread
cursor[bot] marked this conversation as resolved.

#endif
Loading