From 374647732c8c91fb6e27f4237f05325cd458f28d Mon Sep 17 00:00:00 2001 From: ismail Date: Wed, 27 Aug 2025 14:06:37 +0300 Subject: [PATCH] Fix possible integer underflow bug Fixed a possible integer underflow bug that may cause the timer to be set for an unexpectedly long duration. Fixes #1091 --- src/relay_chn_core.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/relay_chn_core.c b/src/relay_chn_core.c index f062e1b..4119062 100644 --- a/src/relay_chn_core.c +++ b/src/relay_chn_core.c @@ -327,19 +327,27 @@ void relay_chn_issue_cmd(relay_chn_ctl_t* chn_ctl, relay_chn_cmd_t cmd) // If the last run command is different from the current command, calculate the time passed // since the last run command stopped and decide whether to run the command immediately or wait uint32_t last_run_cmd_time_ms = relay_chn_run_info_get_last_run_cmd_time_ms(chn_ctl->run_info); - uint32_t inertia_time_passed_ms = (uint32_t) (esp_timer_get_time() / 1000) - last_run_cmd_time_ms; - uint32_t inertia_time_ms = CONFIG_RELAY_CHN_OPPOSITE_INERTIA_MS - inertia_time_passed_ms; - if (inertia_time_ms > 0) { - chn_ctl->pending_cmd = cmd; - relay_chn_state_t new_state = cmd == RELAY_CHN_CMD_FORWARD - ? RELAY_CHN_STATE_FORWARD_PENDING : RELAY_CHN_STATE_REVERSE_PENDING; - relay_chn_update_state(chn_ctl, new_state); - // If the time passed is less than the opposite inertia time, wait for the remaining time - relay_chn_start_esp_timer_once(chn_ctl->inertia_timer, inertia_time_ms); - } - else { - // If the time passed is more than the opposite inertia time, run the command immediately + uint32_t current_time_ms = (uint32_t)(esp_timer_get_time() / 1000); + if (current_time_ms < last_run_cmd_time_ms) { // Timer overflow + // If timer overflowed, it's been a long time. Run immediately. relay_chn_dispatch_cmd(chn_ctl, cmd); + } else { + uint32_t inertia_time_passed_ms = current_time_ms - last_run_cmd_time_ms; + if (inertia_time_passed_ms < CONFIG_RELAY_CHN_OPPOSITE_INERTIA_MS) { + uint32_t inertia_time_ms = CONFIG_RELAY_CHN_OPPOSITE_INERTIA_MS - inertia_time_passed_ms; + chn_ctl->pending_cmd = cmd; + relay_chn_state_t new_state = cmd == RELAY_CHN_CMD_FORWARD + ? RELAY_CHN_STATE_FORWARD_PENDING : RELAY_CHN_STATE_REVERSE_PENDING; + relay_chn_update_state(chn_ctl, new_state); + // If the time passed is less than the opposite inertia time, wait for the remaining time + if (relay_chn_start_esp_timer_once(chn_ctl->inertia_timer, inertia_time_ms) != ESP_OK) { + ESP_LOGE(TAG, "Failed to start inertia timer for ch %d", chn_ctl->id); + relay_chn_execute_idle(chn_ctl); + } + } else { + // If the time passed is more than the opposite inertia time, run the command immediately + relay_chn_dispatch_cmd(chn_ctl, cmd); + } } } break;