summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKiall Mac Innes <kiall@macinnes.ie>2015-07-03 14:56:31 +0100
committerKiall Mac Innes <kiall@macinnes.ie>2015-07-20 18:54:44 +0000
commit09d65fddf1abfe9d7a3f3e63b87a03bea06e61ce (patch)
treea23fdbd5728272328a1eaf4cb47b2d2cc521a0dd
parent2612d4875c854c4ffbc497f3e4c898721f89ed6d (diff)
downloaddesignate-09d65fddf1abfe9d7a3f3e63b87a03bea06e61ce.tar.gz
Ensure validations account for trailing newlines
The regex's used for validation allowed "\n" terminated strings to pass, allowing invalid data through. Change-Id: Iae4c40ffab9951280bb6d67c2a7cb779dc7ddf0f Closes-Bug: 1471158
-rw-r--r--designate/schema/format.py13
-rw-r--r--designate/tests/test_schema/test_format.py53
2 files changed, 63 insertions, 3 deletions
diff --git a/designate/schema/format.py b/designate/schema/format.py
index c083ded6..c1efa705 100644
--- a/designate/schema/format.py
+++ b/designate/schema/format.py
@@ -24,12 +24,19 @@ from designate.openstack.common import log as logging
LOG = logging.getLogger(__name__)
-RE_DOMAINNAME = r'^(?!.{255,})(?:(?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-)\.)+$'
-RE_HOSTNAME = r'^(?!.{255,})(?:(^\*|(?!\-)[A-Za-z0-9_\-]{1,63})(?<!\-)\.)+$'
+# NOTE(kiall): All of the below regular expressions are termined with
+# "(?![\n])$", rather than simply "$" to ensure a string with a
+# trailing newline is NOT matched. See bug #1471158. Annoyingly,
+# Python's re module has no equilivant to PCRE_DOLLAR_ENDONLY, so
+# we do it by hand instead.
+
+RE_DOMAINNAME = r'^(?!.{255,})(?:(?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-)\.)+\Z'
+RE_HOSTNAME = r'^(?!.{255,})(?:(?:^\*|(?!\-)[A-Za-z0-9_\-]{1,63})(?<!\-)\.)+\Z'
# The TLD name will not end in a period.
RE_TLDNAME = r'^(?!.{255,})(?:(?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-))' \
- r'(\.(?:(?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-)))*$'
+ r'(?:\.(?:(?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-)))*\Z'
+
draft3_format_checker = jsonschema.draft3_format_checker
draft4_format_checker = jsonschema.draft4_format_checker
diff --git a/designate/tests/test_schema/test_format.py b/designate/tests/test_schema/test_format.py
index 847d21a0..8bb28b16 100644
--- a/designate/tests/test_schema/test_format.py
+++ b/designate/tests/test_schema/test_format.py
@@ -45,6 +45,8 @@ class SchemaFormatTest(TestCase):
'ABCDEF',
'ABC/DEF',
'ABC\\DEF',
+ # Trailing newline - Bug 1471158
+ "127.0.0.1\n",
]
for ipaddress in valid_ipaddresses:
@@ -53,6 +55,29 @@ class SchemaFormatTest(TestCase):
for ipaddress in invalid_ipaddresses:
self.assertFalse(format.is_ipv4(ipaddress))
+ def test_is_ipv6(self):
+ valid_ipaddresses = [
+ '2001:db8::0',
+ '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ '2001:db8:85a3:0000:0000:8a2e:0370:7334',
+ '2001:db8:85a3::8a2e:0370:7334',
+ ]
+
+ invalid_ipaddresses = [
+ # Invalid characters
+ 'hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh'
+ # Trailing newline - Bug 1471158
+ "2001:db8::0\n",
+ ]
+
+ for ipaddress in valid_ipaddresses:
+ self.assertTrue(format.is_ipv6(ipaddress),
+ 'Expected Valid: %s' % ipaddress)
+
+ for ipaddress in invalid_ipaddresses:
+ self.assertFalse(format.is_ipv6(ipaddress),
+ 'Expected Invalid: %s' % ipaddress)
+
def test_is_hostname(self):
valid_hostnames = [
'example.com.',
@@ -112,6 +137,8 @@ class SchemaFormatTest(TestCase):
'-abc-.',
'abc.-def-.',
'abc.-def-.ghi.',
+ # Trailing newline - Bug 1471158
+ "www.example.com.\n",
]
for hostname in valid_hostnames:
@@ -182,6 +209,8 @@ class SchemaFormatTest(TestCase):
'-abc-.',
'abc.-def-.',
'abc.-def-.ghi.',
+ # Trailing newline - Bug 1471158
+ "example.com.\n",
]
for domainname in valid_domainnames:
@@ -190,6 +219,30 @@ class SchemaFormatTest(TestCase):
for domainname in invalid_domainnames:
self.assertFalse(format.is_domainname(domainname))
+ def test_is_tldname(self):
+ valid_tldnames = [
+ 'com',
+ 'net',
+ 'org',
+ 'co.uk',
+ ]
+
+ invalid_tldnames = [
+ # Invalid Formats
+ 'com.',
+ '.com',
+ # Trailing newline - Bug 1471158
+ "com\n",
+ ]
+
+ for tldname in valid_tldnames:
+ self.assertTrue(format.is_tldname(tldname),
+ 'Expected Valid: %s' % tldname)
+
+ for tldname in invalid_tldnames:
+ self.assertFalse(format.is_tldname(tldname),
+ 'Expected Invalid: %s' % tldname)
+
def test_is_email(self):
valid_emails = [
'user@example.com',