fix(mdns): Fix Unbounded recursion in mDNS name decompression

This commit is contained in:
David Cermak
2026-06-10 11:56:35 +02:00
parent c6bf2deb2c
commit 95c882c7d7
3 changed files with 24 additions and 7 deletions
+4 -2
View File
@@ -258,13 +258,15 @@ void static dbg_packet(const uint8_t *data, size_t len)
dbg_printf("%" PRIu32, ttl);
dbg_printf("[%u] ", data_len);
if (type == MDNS_TYPE_PTR) {
if (!mdns_utils_parse_fqdn(data, data_ptr, name, len)) {
size_t rdata_bound = (size_t)(data_ptr + data_len - data);
if (!mdns_utils_parse_fqdn(data, data_ptr, name, rdata_bound)) {
dbg_printf("ERROR: parse PTR\n");
continue;
}
dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain);
} else if (type == MDNS_TYPE_SRV) {
if (!mdns_utils_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) {
size_t rdata_bound = (size_t)(data_ptr + data_len - data);
if (!mdns_utils_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, rdata_bound)) {
dbg_printf("ERROR: parse SRV\n");
continue;
}
+4 -2
View File
@@ -855,7 +855,8 @@ static void mdns_parse_packet(mdns_rx_packet_t *packet)
if (type == MDNS_TYPE_PTR) {
mdns_browse_t *browse_for_ptr = mdns_priv_browse_find_ptr(name);
if (!mdns_utils_parse_fqdn(data, data_ptr, name, len)) {
size_t rdata_bound = (size_t)(data_ptr + data_len - data);
if (!mdns_utils_parse_fqdn(data, data_ptr, name, rdata_bound)) {
continue;//error
}
if (browse_for_ptr) {
@@ -947,7 +948,8 @@ static void mdns_parse_packet(mdns_rx_packet_t *packet)
}
}
bool is_selfhosted = is_name_selfhosted(name);
if (!mdns_utils_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) {
size_t rdata_bound = (size_t)(data_ptr + data_len - data);
if (!mdns_utils_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, rdata_bound)) {
continue;
}
if (data_ptr + MDNS_SRV_PORT_OFFSET + 1 >= data + len) {
+16 -3
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,7 +15,10 @@ static const char *TAG = "mdns_utils";
static const char *MDNS_DEFAULT_DOMAIN = "local";
static const char *MDNS_SUB_STR = "_sub";
const uint8_t *mdns_utils_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len)
#define MDNS_FQDN_MAX_COMPRESSION_DEPTH 16
static const uint8_t *mdns_utils_read_fqdn_impl(const uint8_t *packet, const uint8_t *start, mdns_name_t *name,
char *buf, size_t packet_len, unsigned compression_depth)
{
size_t index = 0;
const uint8_t *packet_end = packet + packet_len;
@@ -63,7 +66,11 @@ const uint8_t *mdns_utils_read_fqdn(const uint8_t *packet, const uint8_t *start,
//reference address can not be after where we are
return NULL;
}
if (mdns_utils_read_fqdn(packet, packet + address, name, buf, packet_len)) {
if (compression_depth >= MDNS_FQDN_MAX_COMPRESSION_DEPTH) {
return NULL;
}
if (mdns_utils_read_fqdn_impl(packet, packet + address, name, buf, packet_len,
compression_depth + 1)) {
return start + index;
}
return NULL;
@@ -72,6 +79,12 @@ const uint8_t *mdns_utils_read_fqdn(const uint8_t *packet, const uint8_t *start,
return start + index + 1;
}
const uint8_t *mdns_utils_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf,
size_t packet_len)
{
return mdns_utils_read_fqdn_impl(packet, start, name, buf, packet_len, 0);
}
const uint8_t *mdns_utils_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len)
{
name->parts = 0;