Skip to content

Commit f816ce1

Browse files
authored
Improve IPv6 validation (#201)
* Improve IPv6 validation fixes #107 * Add some comments * Fix ipv4 with double colon * Fix falsy to long ipv6 result and detect to long parts * Check for length * Take empty parts in account * Reduce length calculation
1 parent 29df081 commit f816ce1

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

tests/test_ipv6.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55

66

77
@pytest.mark.parametrize(('address',), [
8+
('::',),
89
('::1',),
9-
('dead:beef:0:0:0:0:42:1',),
10+
('1::',),
11+
('dead:beef:0:0:0:0000:42:1',),
1012
('abcd:ef::42:1',),
1113
('0:0:0:0:0:ffff:1.2.3.4',),
1214
('::192.168.30.2',),
15+
('0000:0000:0000:0000:0000::',),
16+
('0:a:b:c:d:e:f::',),
1317
])
1418
def test_returns_true_on_valid_ipv6_address(address):
1519
assert ipv6(address)
@@ -20,7 +24,19 @@ def test_returns_true_on_valid_ipv6_address(address):
2024
('abc.0.0.1',),
2125
('abcd:1234::123::1',),
2226
('1:2:3:4:5:6:7:8:9',),
27+
('1:2:3:4:5:6:7:8::',),
28+
('1:2:3:4:5:6:7::8:9',),
2329
('abcd::1ffff',),
30+
('1111:',),
31+
(':8888',),
32+
(':1.2.3.4',),
33+
('18:05',),
34+
(':',),
35+
(':1:2:',),
36+
(':1:2::',),
37+
('::1:2::',),
38+
('8::1:2::9',),
39+
('02001:0000:1234:0000:0000:C1C0:ABCD:0876',),
2440
])
2541
def test_returns_failed_validation_on_invalid_ipv6_address(address):
2642
assert isinstance(ipv6(address), ValidationFailure)

validators/ip_address.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
@validator
55
def ipv4(value):
66
"""
7-
Return whether or not given value is a valid IP version 4 address.
7+
Return whether a given value is a valid IP version 4 address.
88
99
This validator is based on `WTForms IPAddress validator`_
1010
@@ -32,7 +32,7 @@ def ipv4(value):
3232
@validator
3333
def ipv4_cidr(value):
3434
"""
35-
Return whether or not given value is a valid CIDR-notated IP version 4
35+
Return whether a given value is a valid CIDR-notated IP version 4
3636
address range.
3737
3838
This validator is based on RFC4632 3.1.
@@ -57,7 +57,7 @@ def ipv4_cidr(value):
5757
@validator
5858
def ipv6(value):
5959
"""
60-
Return whether or not given value is a valid IP version 6 address
60+
Return whether a given value is a valid IP version 6 address
6161
(including IPv4-mapped IPv6 addresses).
6262
6363
This validator is based on `WTForms IPAddress validator`_.
@@ -95,10 +95,6 @@ def ipv6(value):
9595
else:
9696
ipv4_groups = []
9797

98-
max_groups = 6 if ipv4_groups else 8
99-
if len(ipv6_groups) > max_groups:
100-
return False
101-
10298
count_blank = 0
10399
for part in ipv6_groups:
104100
if not part:
@@ -109,20 +105,32 @@ def ipv6(value):
109105
except ValueError:
110106
return False
111107
else:
112-
if not 0 <= num <= 65536:
108+
if not 0 <= num <= 65536 or len(part) > 4:
113109
return False
114110

115-
if count_blank < 2:
111+
max_groups = 6 if ipv4_groups else 8
112+
part_count = len(ipv6_groups) - count_blank
113+
if count_blank == 0 and part_count == max_groups:
114+
# no :: -> must have size of max_groups
115+
return True
116+
elif count_blank == 1 and ipv6_groups[-1] and ipv6_groups[0] and part_count < max_groups:
117+
# one :: inside the address or prefix or suffix : -> filter least two cases
118+
return True
119+
elif count_blank == 2 and part_count < max_groups and (
120+
((ipv6_groups[0] and not ipv6_groups[-1]) or (not ipv6_groups[0] and ipv6_groups[-1])) or ipv4_groups):
121+
# leading or trailing :: or : at end and begin -> filter last case
122+
# Check if it has ipv4 groups because they get removed from the ipv6_groups
116123
return True
117-
elif count_blank == 2 and not ipv6_groups[0] and not ipv6_groups[1]:
124+
elif count_blank == 3 and part_count == 0:
125+
# :: is the address -> filter everything else
118126
return True
119127
return False
120128

121129

122130
@validator
123131
def ipv6_cidr(value):
124132
"""
125-
Returns whether or not given value is a valid CIDR-notated IP version 6
133+
Returns whether a given value is a valid CIDR-notated IP version 6
126134
address range.
127135
128136
This validator is based on RFC4632 3.1.

0 commit comments

Comments
 (0)