summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Halley <halley@dnspython.org>2020-08-25 07:32:11 -0700
committerBob Halley <halley@dnspython.org>2020-08-25 07:32:11 -0700
commitf65cd9fa9cbf8ae19bad346dcad5d90b33ed9625 (patch)
treefb2a9dc46fd2efa795ace8049866a6014f48d3ee
parent160bdf2657f673c10f64c76026007d3ce87faee2 (diff)
downloaddnspython-f65cd9fa9cbf8ae19bad346dcad5d90b33ed9625.tar.gz
remove _constify() uses; more complete checking of bitmap windows types like NSEC
-rw-r--r--dns/rdata.py2
-rw-r--r--dns/rdtypes/ANY/CSYNC.py14
-rw-r--r--dns/rdtypes/ANY/HIP.py3
-rw-r--r--dns/rdtypes/ANY/LOC.py4
-rw-r--r--dns/rdtypes/ANY/NSEC.py12
-rw-r--r--dns/rdtypes/ANY/NSEC3.py14
-rw-r--r--dns/rdtypes/ANY/OPT.py2
-rw-r--r--dns/rdtypes/ANY/TSIG.py2
-rw-r--r--dns/rdtypes/IN/APL.py2
-rw-r--r--dns/rdtypes/IN/WKS.py2
-rw-r--r--dns/rdtypes/txtbase.py2
-rw-r--r--dns/rdtypes/util.py37
-rw-r--r--tests/test_rdata.py38
13 files changed, 79 insertions, 55 deletions
diff --git a/dns/rdata.py b/dns/rdata.py
index 042623d..3a49954 100644
--- a/dns/rdata.py
+++ b/dns/rdata.py
@@ -350,6 +350,8 @@ class Rdata:
def _as_bytes(cls, value, encode=False, max_length=None):
if encode and isinstance(value, str):
value = value.encode()
+ elif isinstance(value, bytearray):
+ value = bytes(value)
elif not isinstance(value, bytes):
raise ValueError('not bytes')
if max_length is not None and len(value) > max_length:
diff --git a/dns/rdtypes/ANY/CSYNC.py b/dns/rdtypes/ANY/CSYNC.py
index 0c33728..268fd88 100644
--- a/dns/rdtypes/ANY/CSYNC.py
+++ b/dns/rdtypes/ANY/CSYNC.py
@@ -41,7 +41,11 @@ class CSYNC(dns.rdata.Rdata):
super().__init__(rdclass, rdtype)
self.serial = self._as_uint32(serial)
self.flags = self._as_uint16(flags)
- self.windows = dns.rdata._constify(windows)
+ if isinstance(windows, Bitmap):
+ bitmap = windows
+ else:
+ bitmap = Bitmap(windows)
+ self.windows = tuple(bitmap.windows)
def to_text(self, origin=None, relativize=True, **kw):
text = Bitmap(self.windows).to_text()
@@ -52,8 +56,8 @@ class CSYNC(dns.rdata.Rdata):
relativize_to=None):
serial = tok.get_uint32()
flags = tok.get_uint16()
- windows = Bitmap().from_text(tok)
- return cls(rdclass, rdtype, serial, flags, windows)
+ bitmap = Bitmap.from_text(tok)
+ return cls(rdclass, rdtype, serial, flags, bitmap)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
file.write(struct.pack('!IH', self.serial, self.flags))
@@ -62,5 +66,5 @@ class CSYNC(dns.rdata.Rdata):
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
(serial, flags) = parser.get_struct("!IH")
- windows = Bitmap().from_wire_parser(parser)
- return cls(rdclass, rdtype, serial, flags, windows)
+ bitmap = Bitmap.from_wire_parser(parser)
+ return cls(rdclass, rdtype, serial, flags, bitmap)
diff --git a/dns/rdtypes/ANY/HIP.py b/dns/rdtypes/ANY/HIP.py
index 610260d..f3cb34e 100644
--- a/dns/rdtypes/ANY/HIP.py
+++ b/dns/rdtypes/ANY/HIP.py
@@ -39,8 +39,7 @@ class HIP(dns.rdata.Rdata):
self.hit = self._as_bytes(hit, True, 255)
self.algorithm = self._as_uint8(algorithm)
self.key = self._as_bytes(key, True)
- self.servers = dns.rdata._constify([dns.rdata.Rdata._as_name(s)
- for s in servers])
+ self.servers = tuple([dns.rdata.Rdata._as_name(s) for s in servers])
def to_text(self, origin=None, relativize=True, **kw):
hit = binascii.hexlify(self.hit).decode()
diff --git a/dns/rdtypes/ANY/LOC.py b/dns/rdtypes/ANY/LOC.py
index 60b10b9..1a4ee2b 100644
--- a/dns/rdtypes/ANY/LOC.py
+++ b/dns/rdtypes/ANY/LOC.py
@@ -131,13 +131,13 @@ class LOC(dns.rdata.Rdata):
if isinstance(latitude, float):
latitude = _float_to_tuple(latitude)
_check_coordinate_list(latitude, -90, 90)
- self.latitude = dns.rdata._constify(latitude)
+ self.latitude = tuple(latitude)
if isinstance(longitude, int):
longitude = float(longitude)
if isinstance(longitude, float):
longitude = _float_to_tuple(longitude)
_check_coordinate_list(longitude, -180, 180)
- self.longitude = dns.rdata._constify(longitude)
+ self.longitude = tuple(longitude)
self.altitude = float(altitude)
self.size = float(size)
self.horizontal_precision = float(hprec)
diff --git a/dns/rdtypes/ANY/NSEC.py b/dns/rdtypes/ANY/NSEC.py
index c1d7000..62e4499 100644
--- a/dns/rdtypes/ANY/NSEC.py
+++ b/dns/rdtypes/ANY/NSEC.py
@@ -38,7 +38,11 @@ class NSEC(dns.rdata.Rdata):
def __init__(self, rdclass, rdtype, next, windows):
super().__init__(rdclass, rdtype)
self.next = self._as_name(next)
- self.windows = dns.rdata._constify(windows)
+ if isinstance(windows, Bitmap):
+ bitmap = windows
+ else:
+ bitmap = Bitmap(windows)
+ self.windows = tuple(bitmap.windows)
def to_text(self, origin=None, relativize=True, **kw):
next = self.next.choose_relativity(origin, relativize)
@@ -49,7 +53,7 @@ class NSEC(dns.rdata.Rdata):
def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True,
relativize_to=None):
next = tok.get_name(origin, relativize, relativize_to)
- windows = Bitmap().from_text(tok)
+ windows = Bitmap.from_text(tok)
return cls(rdclass, rdtype, next, windows)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
@@ -59,5 +63,5 @@ class NSEC(dns.rdata.Rdata):
@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
next = parser.get_name(origin)
- windows = Bitmap().from_wire_parser(parser)
- return cls(rdclass, rdtype, next, windows)
+ bitmap = Bitmap.from_wire_parser(parser)
+ return cls(rdclass, rdtype, next, bitmap)
diff --git a/dns/rdtypes/ANY/NSEC3.py b/dns/rdtypes/ANY/NSEC3.py
index 7650552..48a76ee 100644
--- a/dns/rdtypes/ANY/NSEC3.py
+++ b/dns/rdtypes/ANY/NSEC3.py
@@ -58,7 +58,11 @@ class NSEC3(dns.rdata.Rdata):
self.iterations = self._as_uint16(iterations)
self.salt = self._as_bytes(salt, True, 255)
self.next = self._as_bytes(next, True, 255)
- self.windows = dns.rdata._constify(windows)
+ if isinstance(windows, Bitmap):
+ bitmap = windows
+ else:
+ bitmap = Bitmap(windows)
+ self.windows = tuple(bitmap.windows)
def to_text(self, origin=None, relativize=True, **kw):
next = base64.b32encode(self.next).translate(
@@ -85,9 +89,9 @@ class NSEC3(dns.rdata.Rdata):
next = tok.get_string().encode(
'ascii').upper().translate(b32_hex_to_normal)
next = base64.b32decode(next)
- windows = Bitmap().from_text(tok)
+ bitmap = Bitmap.from_text(tok)
return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
- windows)
+ bitmap)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
l = len(self.salt)
@@ -104,6 +108,6 @@ class NSEC3(dns.rdata.Rdata):
(algorithm, flags, iterations) = parser.get_struct('!BBH')
salt = parser.get_counted_bytes()
next = parser.get_counted_bytes()
- windows = Bitmap().from_wire_parser(parser)
+ bitmap = Bitmap.from_wire_parser(parser)
return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
- windows)
+ bitmap)
diff --git a/dns/rdtypes/ANY/OPT.py b/dns/rdtypes/ANY/OPT.py
index 1968ce2..cac54bd 100644
--- a/dns/rdtypes/ANY/OPT.py
+++ b/dns/rdtypes/ANY/OPT.py
@@ -48,7 +48,7 @@ class OPT(dns.rdata.Rdata):
for option in options:
if not isinstance(option, dns.edns.Option):
raise ValueError('option is not a dns.edns.option')
- self.options = dns.rdata._constify(options)
+ self.options = tuple(options)
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
for opt in self.options:
diff --git a/dns/rdtypes/ANY/TSIG.py b/dns/rdtypes/ANY/TSIG.py
index e49bf73..5462195 100644
--- a/dns/rdtypes/ANY/TSIG.py
+++ b/dns/rdtypes/ANY/TSIG.py
@@ -59,7 +59,7 @@ class TSIG(dns.rdata.Rdata):
self.algorithm = self._as_name(algorithm)
self.time_signed = self._as_uint48(time_signed)
self.fudge = self._as_uint16(fudge)
- self.mac = dns.rdata._constify(self._as_bytes(mac))
+ self.mac = self._as_bytes(mac)
self.original_id = self._as_uint16(original_id)
self.error = dns.rcode.Rcode.make(error)
self.other = self._as_bytes(other)
diff --git a/dns/rdtypes/IN/APL.py b/dns/rdtypes/IN/APL.py
index c0cd849..5cfdc34 100644
--- a/dns/rdtypes/IN/APL.py
+++ b/dns/rdtypes/IN/APL.py
@@ -91,7 +91,7 @@ class APL(dns.rdata.Rdata):
for item in items:
if not isinstance(item, APLItem):
raise ValueError('item not an APLItem')
- self.items = dns.rdata._constify(items)
+ self.items = tuple(items)
def to_text(self, origin=None, relativize=True, **kw):
return ' '.join(map(str, self.items))
diff --git a/dns/rdtypes/IN/WKS.py b/dns/rdtypes/IN/WKS.py
index 068b1e3..0d36281 100644
--- a/dns/rdtypes/IN/WKS.py
+++ b/dns/rdtypes/IN/WKS.py
@@ -39,7 +39,7 @@ class WKS(dns.rdata.Rdata):
super().__init__(rdclass, rdtype)
self.address = self._as_ipv4_address(address)
self.protocol = self._as_uint8(protocol)
- self.bitmap = self._as_bytes(dns.rdata._constify(bitmap))
+ self.bitmap = self._as_bytes(bitmap)
def to_text(self, origin=None, relativize=True, **kw):
bits = []
diff --git a/dns/rdtypes/txtbase.py b/dns/rdtypes/txtbase.py
index a170ced..37bf961 100644
--- a/dns/rdtypes/txtbase.py
+++ b/dns/rdtypes/txtbase.py
@@ -48,7 +48,7 @@ class TXTBase(dns.rdata.Rdata):
for string in strings:
string = self._as_bytes(string, True, 255)
encoded_strings.append(string)
- self.strings = dns.rdata._constify(encoded_strings)
+ self.strings = tuple(encoded_strings)
def to_text(self, origin=None, relativize=True, **kw):
txt = ''
diff --git a/dns/rdtypes/util.py b/dns/rdtypes/util.py
index bac7e7a..03afb32 100644
--- a/dns/rdtypes/util.py
+++ b/dns/rdtypes/util.py
@@ -99,7 +99,22 @@ class Bitmap:
type_name = ""
def __init__(self, windows=None):
+ last_window = -1
self.windows = windows
+ for (window, bitmap) in self.windows:
+ if not isinstance(window, int):
+ raise ValueError(f"bad {self.type_name} window type")
+ if not isinstance(window, int):
+ raise ValueError(f"bad {self.type_name} window type")
+ if window <= last_window:
+ raise ValueError(f"bad {self.type_name} window order")
+ if window > 256:
+ raise ValueError(f"bad {self.type_name} window number")
+ last_window = window
+ if not isinstance(bitmap, bytes):
+ raise ValueError(f"bad {self.type_name} octets type")
+ if len(bitmap) == 0 or len(bitmap) > 32:
+ raise ValueError(f"bad {self.type_name} octets")
def to_text(self):
text = ""
@@ -113,12 +128,13 @@ class Bitmap:
text += (' ' + ' '.join(bits))
return text
- def from_text(self, tok):
+ @classmethod
+ def from_text(cls, tok):
rdtypes = []
for token in tok.get_remaining():
rdtype = dns.rdatatype.from_text(token.unescape().value)
if rdtype == 0:
- raise dns.exception.SyntaxError(f"{self.type_name} with bit 0")
+ raise dns.exception.SyntaxError(f"{cls.type_name} with bit 0")
rdtypes.append(rdtype)
rdtypes.sort()
window = 0
@@ -133,7 +149,7 @@ class Bitmap:
new_window = rdtype // 256
if new_window != window:
if octets != 0:
- windows.append((window, bitmap[0:octets]))
+ windows.append((window, bytes(bitmap[0:octets])))
bitmap = bytearray(b'\0' * 32)
window = new_window
offset = rdtype % 256
@@ -142,24 +158,19 @@ class Bitmap:
octets = byte + 1
bitmap[byte] = bitmap[byte] | (0x80 >> bit)
if octets != 0:
- windows.append((window, bitmap[0:octets]))
- return windows
+ windows.append((window, bytes(bitmap[0:octets])))
+ return cls(windows)
def to_wire(self, file):
for (window, bitmap) in self.windows:
file.write(struct.pack('!BB', window, len(bitmap)))
file.write(bitmap)
- def from_wire_parser(self, parser):
+ @classmethod
+ def from_wire_parser(cls, parser):
windows = []
- last_window = -1
while parser.remaining() > 0:
window = parser.get_uint8()
- if window <= last_window:
- raise dns.exception.FormError(f"bad {self.type_name} bitmap")
bitmap = parser.get_counted_bytes()
- if len(bitmap) == 0 or len(bitmap) > 32:
- raise dns.exception.FormError(f"bad {self.type_name} octets")
windows.append((window, bitmap))
- last_window = window
- return windows
+ return cls(windows)
diff --git a/tests/test_rdata.py b/tests/test_rdata.py
index 41465e0..956bec0 100644
--- a/tests/test_rdata.py
+++ b/tests/test_rdata.py
@@ -667,73 +667,73 @@ class UtilTestCase(unittest.TestCase):
g.from_wire_parser(None)
def test_Bitmap(self):
- b = dns.rdtypes.util.Bitmap([])
+ b = dns.rdtypes.util.Bitmap
tok = dns.tokenizer.Tokenizer('A MX')
- windows = b.from_text(tok)
+ windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0x40) # bit 1, for A
ba.append(0x01) # bit 15, for MX
- self.assertEqual(windows, [(0, ba)])
+ self.assertEqual(windows, [(0, bytes(ba))])
def test_Bitmap_with_duplicate_types(self):
- b = dns.rdtypes.util.Bitmap([])
+ b = dns.rdtypes.util.Bitmap
tok = dns.tokenizer.Tokenizer('A MX A A MX')
- windows = b.from_text(tok)
+ windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0x40) # bit 1, for A
ba.append(0x01) # bit 15, for MX
- self.assertEqual(windows, [(0, ba)])
+ self.assertEqual(windows, [(0, bytes(ba))])
def test_Bitmap_with_out_of_order_types(self):
- b = dns.rdtypes.util.Bitmap([])
+ b = dns.rdtypes.util.Bitmap
tok = dns.tokenizer.Tokenizer('MX A')
- windows = b.from_text(tok)
+ windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0x40) # bit 1, for A
ba.append(0x01) # bit 15, for MX
- self.assertEqual(windows, [(0, ba)])
+ self.assertEqual(windows, [(0, bytes(ba))])
def test_Bitmap_zero_padding_works(self):
- b = dns.rdtypes.util.Bitmap([])
+ b = dns.rdtypes.util.Bitmap
tok = dns.tokenizer.Tokenizer('SRV')
- windows = b.from_text(tok)
+ windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0)
ba.append(0)
ba.append(0)
ba.append(0)
ba.append(0x40) # bit 33, for SRV
- self.assertEqual(windows, [(0, ba)])
+ self.assertEqual(windows, [(0, bytes(ba))])
def test_Bitmap_has_type_0_set(self):
- b = dns.rdtypes.util.Bitmap([])
+ b = dns.rdtypes.util.Bitmap
with self.assertRaises(dns.exception.SyntaxError):
tok = dns.tokenizer.Tokenizer('NONE A MX')
b.from_text(tok)
def test_Bitmap_empty_window_not_written(self):
- b = dns.rdtypes.util.Bitmap([])
+ b = dns.rdtypes.util.Bitmap
tok = dns.tokenizer.Tokenizer('URI CAA') # types 256 and 257
- windows = b.from_text(tok)
+ windows = b.from_text(tok).windows
ba = bytearray()
ba.append(0xc0) # bits 0 and 1 in window 1
- self.assertEqual(windows, [(1, ba)])
+ self.assertEqual(windows, [(1, bytes(ba))])
def test_Bitmap_ok_parse(self):
parser = dns.wire.Parser(b'\x00\x01\x40')
b = dns.rdtypes.util.Bitmap([])
- windows = b.from_wire_parser(parser)
+ windows = b.from_wire_parser(parser).windows
self.assertEqual(windows, [(0, b'@')])
def test_Bitmap_0_length_window_parse(self):
parser = dns.wire.Parser(b'\x00\x00')
- with self.assertRaises(dns.exception.FormError):
+ with self.assertRaises(ValueError):
b = dns.rdtypes.util.Bitmap([])
b.from_wire_parser(parser)
def test_Bitmap_too_long_parse(self):
parser = dns.wire.Parser(b'\x00\x21' + b'\x01' * 33)
- with self.assertRaises(dns.exception.FormError):
+ with self.assertRaises(ValueError):
b = dns.rdtypes.util.Bitmap([])
b.from_wire_parser(parser)