diff --git a/esphome/components/zwave_proxy/zwave_proxy.cpp b/esphome/components/zwave_proxy/zwave_proxy.cpp index f8e0f580e9..8506b19e7f 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.cpp +++ b/esphome/components/zwave_proxy/zwave_proxy.cpp @@ -105,7 +105,7 @@ void ZWaveProxy::process_uart_() { this->buffer_[1] >= ZWAVE_MIN_GET_NETWORK_IDS_LENGTH && this->buffer_[0] == ZWAVE_FRAME_TYPE_START) { // Store the 4-byte Home ID, which starts at offset 4, and notify connected clients if it changed // The frame parser has already validated the checksum and ensured all bytes are present - if (this->set_home_id(&this->buffer_[4])) { + if (this->set_home_id_(&this->buffer_[4])) { this->send_homeid_changed_msg_(); } } @@ -165,7 +165,7 @@ void ZWaveProxy::zwave_proxy_request(api::APIConnection *api_connection, api::en } } -bool ZWaveProxy::set_home_id(const uint8_t *new_home_id) { +bool ZWaveProxy::set_home_id_(const uint8_t *new_home_id) { if (std::memcmp(this->home_id_.data(), new_home_id, this->home_id_.size()) == 0) { ESP_LOGV(TAG, "Home ID unchanged"); return false; // No change @@ -178,19 +178,28 @@ bool ZWaveProxy::set_home_id(const uint8_t *new_home_id) { } void ZWaveProxy::send_frame(const uint8_t *data, size_t length) { - if (length == 1 && data[0] == this->last_response_) { - ESP_LOGV(TAG, "Skipping sending duplicate response: 0x%02X", data[0]); + // Safety: validate pointer before any access + if (data == nullptr) { + ESP_LOGE(TAG, "Null data pointer"); return; } - if (length && data != nullptr) { -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE - char hex_buf[format_hex_pretty_size(ZWAVE_MAX_LOG_BYTES)]; -#endif - ESP_LOGVV(TAG, "Sending: %s", format_hex_pretty_to(hex_buf, data, length)); - this->write_array(data, length); - } else { - ESP_LOGE(TAG, "Null pointer or length 0"); + if (length == 0) { + ESP_LOGE(TAG, "Length 0"); + return; } + + // Skip duplicate single-byte responses (ACK/NAK/CAN) + if (length == 1 && data[0] == this->last_response_) { + ESP_LOGV(TAG, "Response already sent: 0x%02X", data[0]); + return; + } + +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char hex_buf[format_hex_pretty_size(ZWAVE_MAX_LOG_BYTES)]; +#endif + ESP_LOGVV(TAG, "Sending: %s", format_hex_pretty_to(hex_buf, data, length)); + + this->write_array(data, length); } void ZWaveProxy::send_homeid_changed_msg_(api::APIConnection *conn) { diff --git a/esphome/components/zwave_proxy/zwave_proxy.h b/esphome/components/zwave_proxy/zwave_proxy.h index f36287d32a..eb26316f49 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.h +++ b/esphome/components/zwave_proxy/zwave_proxy.h @@ -60,11 +60,11 @@ class ZWaveProxy : public uart::UARTDevice, public Component { uint32_t get_home_id() { return encode_uint32(this->home_id_[0], this->home_id_[1], this->home_id_[2], this->home_id_[3]); } - bool set_home_id(const uint8_t *new_home_id); // Store a new home ID. Returns true if it changed. void send_frame(const uint8_t *data, size_t length); protected: + bool set_home_id_(const uint8_t *new_home_id); // Store a new home ID. Returns true if it changed. void send_homeid_changed_msg_(api::APIConnection *conn = nullptr); void send_simple_command_(uint8_t command_id); bool parse_byte_(uint8_t byte); // Returns true if frame parsing was completed (a frame is ready in the buffer)