Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9035c6a

Browse filesBrowse files
authored
Merge pull request python-zeroconf#77 from stephenrauch/fix-instance-name-with-dot
Allow dots in service instance name
2 parents 136dce9 + e46af83 commit 9035c6a
Copy full SHA for 9035c6a

File tree

Expand file treeCollapse file tree

3 files changed

+50
-18
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+50
-18
lines changed

‎README.rst

Copy file name to clipboardExpand all lines: README.rst
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,14 @@ Changelog
129129
* Many exceptions will now log a warning the first time they are seen
130130
* Catch and log sendto() errors
131131
* Fix/Implement duplicate name change
132+
* Fix overly strict name validation introduced in 0.17.6
132133
* Greatly improve handling of oversized packets including:
133134

134135
- Implement name compression per RFC1035
135136
- Limit size of generated packets to 9000 bytes as per RFC6762
136137
- Better handle over sized incoming packets
137138

138-
* Increased test coverage to 94%
139+
* Increased test coverage to 95%
139140

140141
0.17.6
141142
------

‎test_zeroconf.py

Copy file name to clipboardExpand all lines: test_zeroconf.py
+23-4Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,24 +422,43 @@ def test_bad_service_names(self):
422422
'_22._udp.local.',
423423
'_2-2._tcp.local.',
424424
'_1234567890-abcde._udp.local.',
425-
'._x._udp.local.',
425+
'\x00._x._udp.local.',
426426
)
427427
for name in bad_names_to_try:
428428
self.assertRaises(
429429
r.BadTypeInNameException,
430430
self.browser.get_service_info, name, 'x.' + name)
431431

432-
def test_bad_sub_types(self):
433-
bad_names_to_try = (
434-
'_sub._http._tcp.local.',
432+
def test_good_instance_names(self):
433+
good_names_to_try = (
434+
'.._x._tcp.local.',
435435
'x.sub._http._tcp.local.',
436+
'6d86f882b90facee9170ad3439d72a4d6ee9f511._zget._http._tcp.local.'
437+
)
438+
for name in good_names_to_try:
439+
r.service_type_name(name)
440+
441+
def test_bad_types(self):
442+
bad_names_to_try = (
443+
'._x._tcp.local.',
436444
'a' * 64 + '._sub._http._tcp.local.',
437445
'a' * 62 + u'â._sub._http._tcp.local.',
438446
)
439447
for name in bad_names_to_try:
440448
self.assertRaises(
441449
r.BadTypeInNameException, r.service_type_name, name)
442450

451+
def test_bad_sub_types(self):
452+
bad_names_to_try = (
453+
'_sub._http._tcp.local.',
454+
'._sub._http._tcp.local.',
455+
'\x7f._sub._http._tcp.local.',
456+
'\x1f._sub._http._tcp.local.',
457+
)
458+
for name in bad_names_to_try:
459+
self.assertRaises(
460+
r.BadTypeInNameException, r.service_type_name, name)
461+
443462
def test_good_service_names(self):
444463
good_names_to_try = (
445464
'_x._tcp.local.',

‎zeroconf.py

Copy file name to clipboardExpand all lines: zeroconf.py
+25-13Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ def emit(self, record):
158158

159159
_HAS_A_TO_Z = re.compile(r'[A-Za-z]')
160160
_HAS_ONLY_A_TO_Z_NUM_HYPHEN = re.compile(r'^[A-Za-z0-9\-]+$')
161+
_HAS_ASCII_CONTROL_CHARS = re.compile(r'[\x00-\x1f\x7f]')
161162

162163

163164
@enum.unique
@@ -212,6 +213,14 @@ def service_type_name(type_):
212213
213214
The instance name <Instance> and sub type <sub> may be up to 63 bytes.
214215
216+
The portion of the Service Instance Name is a user-
217+
friendly name consisting of arbitrary Net-Unicode text [RFC5198]. It
218+
MUST NOT contain ASCII control characters (byte values 0x00-0x1F and
219+
0x7F) [RFC20] but otherwise is allowed to contain any characters,
220+
without restriction, including spaces, uppercase, lowercase,
221+
punctuation -- including dots -- accented characters, non-Roman text,
222+
and anything else that may be represented using Net-Unicode.
223+
215224
:param type_: Type, SubType or service name to validate
216225
:return: fully qualified service name (eg: _http._tcp.local.)
217226
"""
@@ -220,15 +229,15 @@ def service_type_name(type_):
220229
"Type '%s' must end with '._tcp.local.' or '._udp.local.'" %
221230
type_)
222231

223-
if type_.startswith('.'):
224-
raise BadTypeInNameException(
225-
"Type '%s' must not start with '.'" % type_)
226-
227232
remaining = type_[:-len('._tcp.local.')].split('.')
228233
name = remaining.pop()
229234
if not name:
230235
raise BadTypeInNameException("No Service name found")
231236

237+
if len(remaining) == 1 and len(remaining[0]) == 0:
238+
raise BadTypeInNameException(
239+
"Type '%s' must not start with '.'" % type_)
240+
232241
if name[0] != '_':
233242
raise BadTypeInNameException(
234243
"Service name (%s) must start with '_'" % name)
@@ -260,20 +269,23 @@ def service_type_name(type_):
260269

261270
if remaining and remaining[-1] == '_sub':
262271
remaining.pop()
263-
if len(remaining) == 0:
272+
if len(remaining) == 0 or len(remaining[0]) == 0:
264273
raise BadTypeInNameException(
265274
"_sub requires a subtype name")
266275

267276
if len(remaining) > 1:
268-
raise BadTypeInNameException(
269-
"Unexpected characters '%s.' in '%s'" % (
270-
'.'.join(remaining[1:]), type_))
277+
remaining = ['.'.join(remaining)]
271278

272279
if remaining:
273280
length = len(remaining[0].encode('utf-8'))
274281
if length > 63:
275282
raise BadTypeInNameException("Too long: '%s'" % remaining[0])
276283

284+
if _HAS_ASCII_CONTROL_CHARS.search(remaining[0]):
285+
raise BadTypeInNameException(
286+
"Ascii control character 0x00-0x1F and 0x7F illegal in '%s'" %
287+
remaining[0])
288+
277289
return '_' + name + type_[-len('._tcp.local.'):]
278290

279291

@@ -1846,13 +1858,13 @@ def unregister_all_services(self):
18461858
def check_service(self, info, allow_name_change):
18471859
"""Checks the network for a unique service name, modifying the
18481860
ServiceInfo passed in if it is not unique."""
1849-
service_name = service_type_name(info.name)
18501861

1851-
# This asserts breaks on the current subtype based tests
1862+
# This is kind of funky because of the subtype based tests
18521863
# need to make subtypes a first class citizen
1853-
# assert service_name == info.type
1854-
# instead try:
1855-
assert service_name == '.'.join(info.type.split('.')[-4:])
1864+
service_name = service_type_name(info.name)
1865+
if not info.type.endswith(service_name):
1866+
raise BadTypeInNameException
1867+
18561868
instance_name = info.name[:-len(service_name) - 1]
18571869
next_instance_number = 2
18581870

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.