Terminate the loaded target before logging it, validate udp addresses on the raw lwip branch too, and resolve the socket default in the lwip_tcp test

This commit is contained in:
J. Nick Koston
2026-09-05 13:07:37 +02:00
parent a684e7e67d
commit 7f9812cef6
3 changed files with 23 additions and 13 deletions
@@ -20,6 +20,8 @@ void OutgoingConnectionManager::setup() {
#ifndef API_OUTGOING_CONNECTION_HOST
this->target_pref_ = global_preferences->make_preference<SavedOutgoingTarget>(629847102UL, true);
if (this->target_pref_.load(&this->saved_)) {
// Defend against a corrupt or truncated blob before the first read
this->saved_.host[sizeof(this->saved_.host) - 1] = '\0';
this->host_persisted_ = true;
ESP_LOGD(TAG, "Loaded target %s", this->saved_.host);
} else {
@@ -27,8 +29,6 @@ void OutgoingConnectionManager::setup() {
ESP_LOGD(TAG, "No saved target");
this->saved_ = {};
}
// Defend against a corrupt or truncated preference blob
this->saved_.host[sizeof(this->saved_.host) - 1] = '\0';
#endif
}
+7 -1
View File
@@ -101,9 +101,15 @@ void UDPComponent::setup() {
// 8266 and RP2040 `Duino
for (const auto &address : this->addresses_) {
auto ipaddr = IPAddress();
ipaddr.fromString(address);
if (!ipaddr.fromString(address)) {
ESP_LOGW(TAG, "Invalid address %s", address);
continue;
}
this->ipaddrs_.push_back(ipaddr);
}
if (this->ipaddrs_.size() != this->addresses_.size()) {
this->status_set_warning(LOG_STR("invalid address"));
}
if (this->should_listen_)
this->udp_client_.begin(this->listen_port_);
#endif
@@ -5,6 +5,7 @@ from pathlib import Path
import pytest
from esphome.components import socket
from esphome.components.api import (
CONFIG_SCHEMA,
_validate_outgoing_host_ipv6,
@@ -14,6 +15,7 @@ from esphome.components.esp32 import KEY_BOARD, KEY_VARIANT, VARIANT_ESP32
import esphome.config_validation as cv
from esphome.const import PlatformFramework
from esphome.core import CORE
import esphome.final_validate as fv
from esphome.types import ConfigType
from tests.component_tests.types import SetCoreConfigCallable
@@ -81,26 +83,28 @@ def test_outgoing_connection_requires_encryption(
@pytest.mark.parametrize(
("platform_framework", "platform_data"),
("platform_framework", "platform_data", "socket_conf"),
[
# The platform default on these two
(PlatformFramework.ESP8266_ARDUINO, None),
(PlatformFramework.RP2040_ARDUINO, None),
# The platform default on these two, resolved like AUTO_LOAD does
(PlatformFramework.ESP8266_ARDUINO, None, None),
(PlatformFramework.RP2040_ARDUINO, None, None),
# An explicit selection elsewhere
(PlatformFramework.ESP32_IDF, ESP32_PLATFORM_DATA),
(
PlatformFramework.ESP32_IDF,
ESP32_PLATFORM_DATA,
{"implementation": "lwip_tcp"},
),
],
)
def test_outgoing_connection_rejects_lwip_tcp(
set_core_config: SetCoreConfigCallable,
platform_framework: PlatformFramework,
platform_data: ConfigType | None,
socket_conf: ConfigType | None,
) -> None:
"""The resolved lwip_tcp socket is rejected at final validate."""
set_core_config(
platform_framework,
platform_data=platform_data,
full_config={"socket": {"implementation": "lwip_tcp"}},
)
set_core_config(platform_framework, platform_data=platform_data)
fv.full_config.set({"socket": socket_conf or socket.CONFIG_SCHEMA({})})
config = CONFIG_SCHEMA(_api_config({"host": "192.168.1.2"}))
with pytest.raises(cv.Invalid, match="lwip_tcp"):
_validate_outgoing_socket_implementation(config)