_chunksize = 32
+# We currently allow comparisons for rdata with relative names for backwards
+# compatibility, but in the future we will not, as these kinds of comparisons
+# can lead to subtle bugs if code is not carefully written.
+#
+# This switch allows the future behavior to be turned on so code can be
+# tested with it.
+_allow_relative_comparisons = True
+
class NoRelativeRdataOrdering(dns.exception.DNSException):
"""An attempt was made to do an ordered comparison of one or more
"""Compare an rdata with another rdata of the same rdtype and
rdclass.
- Return < 0 if self < other in the DNSSEC ordering, 0 if self
- == other, and > 0 if self > other.
+ For rdata with only absolute names:
+ Return < 0 if self < other in the DNSSEC ordering, 0 if self
+ == other, and > 0 if self > other.
+ For rdata with at least one relative names:
+ The rdata sorts before any rdata with only absolute names.
+ When compared with another relative rdata, all names are
+ made absolute as if they were relative to the root, as the
+ proper origin is not available. While this creates a stable
+ ordering, it is NOT guaranteed to be the DNSSEC ordering.
+ In the future, all ordering comparisons for rdata with
+ relative names will be disallowed.
"""
try:
our = self.to_digestable()
+ our_relative = False
+ except dns.name.NeedAbsoluteNameOrOrigin:
+ our = self.to_digestable(dns.name.root)
+ our_relative = True
+ try:
their = other.to_digestable()
+ their_relative = False
except dns.name.NeedAbsoluteNameOrOrigin:
+ their = other.to_digestable(dns.name.root)
+ their_relative = True
+ if _allow_relative_comparisons:
+ if our_relative != their_relative:
+ # For the purpose of comparison, all rdata with at least one
+ # relative name is less than an rdata with only absolute names.
+ if our_relative:
+ return -1
+ else:
+ return 1
+ else:
raise NoRelativeRdataOrdering
if our == their:
return 0
new_text = rr.to_text(chunksize=chunksize)
self.assertEqual(output, new_text)
- def test_relative_vs_absolute_compare(self):
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www.')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
- self.assertFalse(r1 == r2)
- self.assertTrue(r1 != r2)
- def bad1():
- r1 < r2
- def bad2():
- r1 <= r2
- def bad3():
- r1 > r2
- def bad4():
- r1 >= r2
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad1)
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad2)
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad3)
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad4)
+ def test_relative_vs_absolute_compare_unstrict(self):
+ try:
+ saved = dns.rdata._allow_relative_comparisons
+ dns.rdata._allow_relative_comparisons = True
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www.')
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
+ self.assertFalse(r1 == r2)
+ self.assertTrue(r1 != r2)
+ self.assertFalse(r1 < r2)
+ self.assertFalse(r1 <= r2)
+ self.assertTrue(r1 > r2)
+ self.assertTrue(r1 >= r2)
+ self.assertTrue(r2 < r1)
+ self.assertTrue(r2 <= r1)
+ self.assertFalse(r2 > r1)
+ self.assertFalse(r2 >= r1)
+ finally:
+ dns.rdata._allow_relative_comparisons = saved
+
+ def test_relative_vs_absolute_compare_strict(self):
+ try:
+ saved = dns.rdata._allow_relative_comparisons
+ dns.rdata._allow_relative_comparisons = False
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www.')
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
+ self.assertFalse(r1 == r2)
+ self.assertTrue(r1 != r2)
+ def bad1():
+ r1 < r2
+ def bad2():
+ r1 <= r2
+ def bad3():
+ r1 > r2
+ def bad4():
+ r1 >= r2
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad1)
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad2)
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad3)
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad4)
+ finally:
+ dns.rdata._allow_relative_comparisons = saved
def test_absolute_vs_absolute_compare(self):
r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www.')
self.assertFalse(r1 > r2)
self.assertFalse(r1 >= r2)
- def test_relative_vs_relative_compare(self):
- r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
- r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'xxx')
- self.assertFalse(r1 == r2)
- self.assertTrue(r1 != r2)
- def bad1():
- r1 < r2
- def bad2():
- r1 <= r2
- def bad3():
- r1 > r2
- def bad4():
- r1 >= r2
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad1)
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad2)
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad3)
- self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad4)
-
+ def test_relative_vs_relative_compare_unstrict(self):
+ try:
+ saved = dns.rdata._allow_relative_comparisons
+ dns.rdata._allow_relative_comparisons = True
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'xxx')
+ self.assertFalse(r1 == r2)
+ self.assertTrue(r1 != r2)
+ self.assertTrue(r1 < r2)
+ self.assertTrue(r1 <= r2)
+ self.assertFalse(r1 > r2)
+ self.assertFalse(r1 >= r2)
+ finally:
+ dns.rdata._allow_relative_comparisons = saved
+
+ def test_relative_vs_relative_compare_strict(self):
+ try:
+ saved = dns.rdata._allow_relative_comparisons
+ dns.rdata._allow_relative_comparisons = False
+ r1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'www')
+ r2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'xxx')
+ self.assertFalse(r1 == r2)
+ self.assertTrue(r1 != r2)
+ def bad1():
+ r1 < r2
+ def bad2():
+ r1 <= r2
+ def bad3():
+ r1 > r2
+ def bad4():
+ r1 >= r2
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad1)
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad2)
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad3)
+ self.assertRaises(dns.rdata.NoRelativeRdataOrdering, bad4)
+ finally:
+ dns.rdata._allow_relative_comparisons = saved
class UtilTestCase(unittest.TestCase):