FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix: keep `key=` distinct from a valueless `key` in TXT records (#1813) · python-zeroconf/python-zeroconf@899eaaa · GitHub

Commit 899eaaa

Browse files
andauthored
fix: keep key= distinct from a valueless key in TXT records (#1813)
Co-authored-by: J. Nick Koston <nick@koston.org>
1 parent 4571f30 commit 899eaaa

3 files changed

Lines changed: 71 additions & 4 deletions

File tree

‎src/zeroconf/_services/info.pxd‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,14 @@ cdef class ServiceInfo(RecordUpdateListener):
8686
@cython.locals(cache=DNSCache)
8787
cpdef bint _load_from_cache(self, object zc, double now)
8888

89-
@cython.locals(length="unsigned char", index="unsigned int", key_value=bytes, key_sep_value=tuple)
89+
@cython.locals(
90+
length="unsigned char",
91+
index="unsigned int",
92+
key_value=bytes,
93+
key=bytes,
94+
sep=bytes,
95+
value=bytes,
96+
)
9097
cdef void _unpack_text_into_properties(self)
9198

9299
@cython.locals(k=bytes, v=bytes)

‎src/zeroconf/_services/info.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,12 @@ def _unpack_text_into_properties(self) -> None:
464464
length = text[index]
465465
index += 1
466466
key_value = text[index : index + length]
467-
key_sep_value = key_value.partition(b"=")
468-
key = key_sep_value[0]
467+
key, sep, value = key_value.partition(b"=")
469468
if key not in properties:
470-
properties[key] = key_sep_value[2] or None
469+
# RFC 6763 section 6.4 distinguishes a key with no '=' (a
470+
# boolean attribute: present, no value) from `key=` (present
471+
# with an empty value), so test the separator, not the value.
472+
properties[key] = value if sep else None
471473
index += length
472474

473475
self._properties = properties

‎tests/services/test_info.py‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,64 @@ def test_service_info_duplicate_properties_txt_records(self):
630630
assert info.properties[b"ci"] == b"2"
631631
zc.close()
632632

633+
def test_service_info_empty_value_txt_record(self):
634+
"""Verify `key=` decodes to an empty value, not to a valueless `key`."""
635+
zc = r.Zeroconf(interfaces=["127.0.0.1"])
636+
service_name = "name._type._tcp.local."
637+
service_type = "_type._tcp.local."
638+
service_server = "ash-1.local."
639+
text = b"\x03rm=\x02rs\x05ve=05"
640+
info = ServiceInfo(
641+
service_type,
642+
service_name,
643+
22,
644+
0,
645+
0,
646+
{"path": "/~paulsm/"},
647+
service_server,
648+
addresses=[socket.inet_aton("10.0.1.2")],
649+
)
650+
info.async_update_records(
651+
zc,
652+
r.current_time_millis(),
653+
[
654+
r.RecordUpdate(
655+
r.DNSText(
656+
service_name,
657+
const._TYPE_TXT,
658+
const._CLASS_IN | const._CLASS_UNIQUE,
659+
120,
660+
text,
661+
),
662+
None,
663+
)
664+
],
665+
)
666+
assert info.properties[b"rm"] == b""
667+
assert info.properties[b"rs"] is None
668+
assert info.properties[b"ve"] == b"05"
669+
670+
# The string-facing API must preserve the distinction too.
671+
assert info.decoded_properties["rm"] == ""
672+
assert info.decoded_properties["rs"] is None
673+
assert info.decoded_properties["ve"] == "05"
674+
675+
# Re-encoding either view of the properties must reproduce the received rdata.
676+
for properties in (info.properties, info.decoded_properties):
677+
assert (
678+
ServiceInfo(
679+
service_type,
680+
service_name,
681+
22,
682+
0,
683+
0,
684+
properties,
685+
service_server,
686+
).text
687+
== text
688+
)
689+
zc.close()
690+
633691

634692
def test_multiple_addresses():
635693
type_ = "_http._tcp.local."

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL