Skip to content

Commit 8ccc0f2

Browse files
committed
Add TXT record size guard to prevent memory exhaustion (CVE-2026-48045)
1 parent fce7094 commit 8ccc0f2

2 files changed

Lines changed: 17 additions & 5 deletions

File tree

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# See https://pre-commit.com for more information
22
# See https://pre-commit.com/hooks.html for more hooks
33
exclude: "CHANGELOG.md"
4-
default_stages: [pre-commit]
4+
default_stages: [commit]
55

66
ci:
77
autofix_commit_msg: "chore(pre-commit.ci): auto fixes"

src/zeroconf/_services/info.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,14 @@ def __init__(
239239
if isinstance(properties, bytes):
240240
self._set_text(properties)
241241
else:
242-
self._set_properties(properties)
242+
# Guard against oversized TXT records
243+
if properties:
244+
for key, value in properties.items():
245+
if value is not None:
246+
val_bytes = value if isinstance(value, bytes) else str(value).encode("utf-8")
247+
if len(val_bytes) > 255: # DNS TXT record limit
248+
raise ValueError("TXT record too large")
249+
self._set_properties(properties or {})
243250
self.host_ttl = host_ttl
244251
self.other_ttl = other_ttl
245252
self._new_records_futures: set[asyncio.Future] | None = None
@@ -411,16 +418,20 @@ def _set_properties(self, properties: dict[str | bytes, str | bytes | None]) ->
411418
if isinstance(key, str):
412419
key = key.encode("utf-8") # noqa: PLW2901
413420
properties_contain_str = True
414-
415421
record = key
416422
if value is not None:
417423
if not isinstance(value, bytes):
418424
value = str(value).encode("utf-8") # noqa: PLW2901
419425
properties_contain_str = True
420426
record += b"=" + value
427+
if len(record) > 255:
428+
raise ValueError("TXT record too large")
429+
421430
list_.append(record)
422-
for item in list_:
423-
result = b"".join((result, bytes((len(item),)), item))
431+
432+
for item in list_:
433+
# Safe encoding only runs if guard passes
434+
result += bytes((len(item),)) + item
424435
if not properties_contain_str:
425436
# If there are no str keys or values, we can use the properties
426437
# as-is, without decoding them, otherwise calling
@@ -429,6 +440,7 @@ def _set_properties(self, properties: dict[str | bytes, str | bytes | None]) ->
429440
self._properties = cast(dict[bytes, bytes | None], properties)
430441
else:
431442
self._properties = properties
443+
432444
self.text = result
433445

434446
def _set_text(self, text: bytes) -> None:

0 commit comments

Comments
 (0)