diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index d9bb2f5fd4..e21af787cb 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1705,10 +1705,10 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes // Null-terminate state in-place for safe c_str() usage (e.g., parse_number in callbacks). // Safe: decode is complete, byte after string data was already consumed during parse, // and frame helpers reserve RX_BUF_NULL_TERMINATOR extra byte in rx_buf_. - // const_cast is safe: msg references rx_buf_ data which is mutable; the const& handler + // const_cast is safe: msg references mutable rx_buf_ data; the const& handler // signature is a generated protobuf pattern, not a true immutability contract. if (!msg.state.empty()) { - const_cast(msg.state).null_terminate_in_place(); + const_cast(msg.state.c_str())[msg.state.size()] = '\0'; } for (auto &it : this->parent_->get_state_subs()) { @@ -1731,11 +1731,11 @@ void APIConnection::on_execute_service_request(const ExecuteServiceRequest &msg) // Null-terminate string args in-place for safe c_str() usage in YAML service triggers. // Safe: full ExecuteServiceRequest decode is complete, all bytes in rx_buf_ consumed, // and frame helpers reserve RX_BUF_NULL_TERMINATOR extra byte for the last field. - // const_cast is safe: msg references rx_buf_ data which is mutable; the const& handler + // const_cast is safe: msg references mutable rx_buf_ data; the const& handler // signature is a generated protobuf pattern, not a true immutability contract. for (auto &arg : const_cast(msg).args) { if (!arg.string_.empty()) { - arg.string_.null_terminate_in_place(); + const_cast(arg.string_.c_str())[arg.string_.size()] = '\0'; } } bool found = false; diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 48694702b1..3ae35e9be8 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -194,18 +194,19 @@ APIError APINoiseFrameHelper::try_read_frame_() { uint16_t msg_size = (((uint16_t) rx_header_buf_[1]) << 8) | rx_header_buf_[2]; // Check against size limits to prevent OOM: MAX_HANDSHAKE_SIZE for handshake, MAX_MESSAGE_SIZE for data - uint16_t limit = (state_ == State::DATA) ? MAX_MESSAGE_SIZE : MAX_HANDSHAKE_SIZE; + bool is_data = (state_ == State::DATA); + uint16_t limit = is_data ? MAX_MESSAGE_SIZE : MAX_HANDSHAKE_SIZE; if (msg_size > limit) { state_ = State::FAILED; HELPER_LOG("Bad packet: message size %u exceeds maximum %u", msg_size, limit); - return (state_ == State::DATA) ? APIError::BAD_DATA_PACKET : APIError::BAD_HANDSHAKE_PACKET_LEN; + return is_data ? APIError::BAD_DATA_PACKET : APIError::BAD_HANDSHAKE_PACKET_LEN; } // Reserve space for body (+ null terminator in DATA state so protobuf // StringRef fields can be safely null-terminated in-place after decode. // During handshake, rx_buf_.size() is used in prologue construction, so // the buffer must be exactly msg_size to avoid prologue mismatch.) - uint16_t alloc_size = msg_size + (state_ == State::DATA ? RX_BUF_NULL_TERMINATOR : 0); + uint16_t alloc_size = msg_size + (is_data ? RX_BUF_NULL_TERMINATOR : 0); if (this->rx_buf_.size() != alloc_size) { this->rx_buf_.resize(alloc_size); } diff --git a/esphome/core/string_ref.h b/esphome/core/string_ref.h index d25b59632c..d502c4d27f 100644 --- a/esphome/core/string_ref.h +++ b/esphome/core/string_ref.h @@ -81,11 +81,6 @@ class StringRef { operator std::string() const { return str(); } - /// Write a null terminator at base_[len_] in-place. - /// Caller must guarantee that the byte at base_[len_] is writable memory - /// (e.g., the RX_BUF_NULL_TERMINATOR byte reserved by frame helpers after decode). - void null_terminate_in_place() { const_cast(base_)[len_] = '\0'; } - /// Find first occurrence of substring, returns std::string::npos if not found. /// Note: Requires the underlying string to be null-terminated. size_type find(const char *s, size_type pos = 0) const {