From cef16575c31a9b0fe03f128ede23e8991cbebe77 Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Mon, 10 Aug 2020 18:12:44 -0700 Subject: [PATCH] detect escapes > 255 --- dns/rdtypes/svcbbase.py | 5 ++++- dns/tokenizer.py | 10 ++++++++-- tests/test_svcb.py | 2 ++ tests/test_tokenizer.py | 8 ++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dns/rdtypes/svcbbase.py b/dns/rdtypes/svcbbase.py index 212b5cdd..9bb83546 100644 --- a/dns/rdtypes/svcbbase.py +++ b/dns/rdtypes/svcbbase.py @@ -122,7 +122,10 @@ def _unescape(value, list_mode=False): i += 1 if not (c2.isdigit() and c3.isdigit()): raise dns.exception.SyntaxError - c = chr(int(c) * 100 + int(c2) * 10 + int(c3)) + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + c = chr(codepoint) unescaped += c.encode() if len(unescaped) > 0: items.append(unescaped) diff --git a/dns/tokenizer.py b/dns/tokenizer.py index 7d698eae..131d428b 100644 --- a/dns/tokenizer.py +++ b/dns/tokenizer.py @@ -120,7 +120,10 @@ class Token: i += 1 if not (c2.isdigit() and c3.isdigit()): raise dns.exception.SyntaxError - c = chr(int(c) * 100 + int(c2) * 10 + int(c3)) + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + c = chr(codepoint) unescaped += c return Token(self.ttype, unescaped) @@ -171,7 +174,10 @@ class Token: i += 1 if not (c2.isdigit() and c3.isdigit()): raise dns.exception.SyntaxError - unescaped += b'%c' % (int(c) * 100 + int(c2) * 10 + int(c3)) + codepoint = int(c) * 100 + int(c2) * 10 + int(c3) + if codepoint > 255: + raise dns.exception.SyntaxError + unescaped += b'%c' % (codepoint) else: # Note that as mentioned above, if c is a Unicode # code point outside of the ASCII range, then this diff --git a/tests/test_svcb.py b/tests/test_svcb.py index 7a6620fc..ecfebf41 100644 --- a/tests/test_svcb.py +++ b/tests/test_svcb.py @@ -275,6 +275,8 @@ class SVCBTestCase(unittest.TestCase): dns.rdata.from_text('in', 'svcb', '1 . alpn=\\00') with self.assertRaises(dns.exception.SyntaxError): dns.rdata.from_text('in', 'svcb', '1 . alpn=\\00q') + with self.assertRaises(dns.exception.SyntaxError): + dns.rdata.from_text('in', 'svcb', '1 . alpn=\\256') # This doesn't usually get exercised, so we do it directly. gp = dns.rdtypes.svcbbase.GenericParam.from_value('\\001\\002') expected = '"\\001\\002"' diff --git a/tests/test_tokenizer.py b/tests/test_tokenizer.py index e4797a5e..6134d4b2 100644 --- a/tests/test_tokenizer.py +++ b/tests/test_tokenizer.py @@ -273,6 +273,14 @@ class TokenizerTestCase(unittest.TestCase): tok = dns.tokenizer.Tokenizer('\\') tok.get() + def testEscapeBounds(self): + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('\\256') + tok.get().unescape() + with self.assertRaises(dns.exception.SyntaxError): + tok = dns.tokenizer.Tokenizer('\\256') + tok.get().unescape_to_bytes() + def testGetUngetRegetComment(self): tok = dns.tokenizer.Tokenizer(';comment') t1 = tok.get(want_comment=True) -- 2.47.3