Blob Blame History Raw
diff -ru dnspython-1.16.0-orig/dns/name.py dnspython-1.16.0/dns/name.py
--- dnspython-1.16.0-orig/dns/name.py	2018-12-05 08:35:40.000000000 -0500
+++ dnspython-1.16.0/dns/name.py	2020-01-22 01:07:53.319289996 -0500
@@ -195,16 +195,10 @@
         self.allow_pure_ascii = allow_pure_ascii
         self.strict_decode = strict_decode
 
-    def is_all_ascii(self, label):
-        for c in label:
-            if ord(c) > 0x7f:
-                return False
-        return True
-
     def encode(self, label):
         if label == '':
             return b''
-        if self.allow_pure_ascii and self.is_all_ascii(label):
+        if self.allow_pure_ascii and is_all_ascii(label):
             return label.encode('ascii')
         if not have_idna_2008:
             raise NoIDNA2008
@@ -230,6 +224,7 @@
             raise IDNAException(idna_exception=e)
 
 _escaped = bytearray(b'"().;\\@$')
+_escaped_text = u'"().;\\@$'
 
 IDNA_2003_Practical = IDNA2003Codec(False)
 IDNA_2003_Strict = IDNA2003Codec(True)
@@ -263,7 +258,9 @@
     if isinstance(label, binary_type):
         label = label.decode()
     for c in label:
-        if c > u'\x20' and c < u'\x7f':
+        if c in _escaped_text:
+            text += u'\\' + c
+        elif c > u'\x20' and c < u'\x7f':
             text += c
         else:
             if c >= u'\x7f':
@@ -827,7 +824,7 @@
     if text == u'@':
         text = u''
     if text:
-        if text == u'.':
+        if text in [u'.', u'\u3002', u'\uff0e', u'\uff61']:
             return Name([b''])        # no Unicode "u" on this constant!
         for c in text:
             if escaping:
@@ -870,6 +867,13 @@
     return Name(labels)
 
 
+def is_all_ascii(text):
+    for c in text:
+        if ord(c) > 0x7f:
+            return False
+    return True
+
+
 def from_text(text, origin=root, idna_codec=None):
     """Convert text into a Name object.
 
@@ -886,7 +890,18 @@
     """
 
     if isinstance(text, text_type):
-        return from_unicode(text, origin, idna_codec)
+        if not is_all_ascii(text):
+            # Some codepoint in the input text is > 127, so IDNA applies.
+            return from_unicode(text, origin, idna_codec)
+        # The input is all ASCII, so treat this like an ordinary non-IDNA
+        # domain name.  Note that "all ASCII" is about the input text,
+        # not the codepoints in the domain name.  E.g. if text has value
+        #
+        # r'\150\151\152\153\154\155\156\157\158\159'
+        #
+        # then it's still "all ASCII" even though the domain name has
+        # codepoints > 127.
+        text = text.encode('ascii')
     if not isinstance(text, binary_type):
         raise ValueError("input to from_text() must be a string")
     if not (origin is None or isinstance(origin, Name)):
diff -ru dnspython-1.16.0-orig/tests/test_name.py dnspython-1.16.0/tests/test_name.py
--- dnspython-1.16.0-orig/tests/test_name.py	2018-12-01 10:48:40.000000000 -0500
+++ dnspython-1.16.0/tests/test_name.py	2020-01-21 23:19:07.998492185 -0500
@@ -255,6 +255,23 @@
         t = dns.name.root.to_unicode()
         self.assertEqual(t, '.')
 
+    def testToText12(self):
+        n = dns.name.from_text(r'a\.b.c')
+        t = n.to_unicode()
+        self.assertEqual(t, r'a\.b.c.')
+
+    def testToText13(self):
+        n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.')
+        t = n.to_text()
+        self.assertEqual(t, r'\150\151\152\153\154\155\156\157\158\159.')
+
+    def testToText14(self):
+        # You can't send this to_unicode() as it wasn't unicode to begin with.
+        def bad():
+            n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.')
+            t = n.to_unicode()
+        self.failUnlessRaises(UnicodeDecodeError, bad)
+
     def testSlice1(self):
         n = dns.name.from_text(r'a.b.c.', origin=None)
         s = n[:]