bpo-36384: Leading zeros in IPv4 addresses are no longer tolerated (GH-25099)

Reverts commit e653d4d8e8 and makes
parsing even more strict. Like socket.inet_pton() any leading zero
is now treated as invalid input.

Signed-off-by: Christian Heimes <christian@python.org>

Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
Christian Heimes 2021-05-02 14:00:35 +02:00 committed by GitHub
parent 73766b0341
commit 60ce8f0be6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 8 deletions

View File

@ -104,8 +104,7 @@ write code that handles both IP versions correctly. Address objects are
1. A string in decimal-dot notation, consisting of four decimal integers in
the inclusive range 0--255, separated by dots (e.g. ``192.168.0.1``). Each
integer represents an octet (byte) in the address. Leading zeroes are
tolerated only for values less than 8 (as there is no ambiguity
between the decimal and octal interpretations of such strings).
not tolerated to prevent confusion with octal notation.
2. An integer that fits into 32 bits.
3. An integer packed into a :class:`bytes` object of length 4 (most
significant octet first).
@ -117,6 +116,22 @@ write code that handles both IP versions correctly. Address objects are
>>> ipaddress.IPv4Address(b'\xC0\xA8\x00\x01')
IPv4Address('192.168.0.1')
.. versionchanged:: 3.8
Leading zeros are tolerated, even in ambiguous cases that look like
octal notation.
.. versionchanged:: 3.10
Leading zeros are no longer tolerated and are treated as an error.
IPv4 address strings are now parsed as strict as glibc
:func:`~socket.inet_pton`.
.. versionchanged:: 3.9.5
The above change was also included in Python 3.9 starting with
version 3.9.5.
.. attribute:: version
The appropriate version number: ``4`` for IPv4, ``6`` for IPv6.

View File

@ -149,8 +149,8 @@ library/ipaddress,,:db8,>>> ipaddress.IPv6Address('2001:db8::1000')
library/ipaddress,,::,>>> ipaddress.IPv6Address('2001:db8::1000')
library/ipaddress,,:db8,'2001:db8::1000'
library/ipaddress,,::,'2001:db8::1000'
library/ipaddress,231,:db8,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
library/ipaddress,231,::,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
library/ipaddress,,:db8,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
library/ipaddress,,::,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
library/ipaddress,,::,IPv6Address('ff02::5678%1')
library/ipaddress,,::,fe80::1234
library/ipaddress,,:db8,">>> ipaddress.ip_address(""2001:db8::1"").reverse_pointer"

1 c-api/arg :ref PyArg_ParseTuple(args, "O|O:ref", &object, &callback)
149 library/ipaddress :: >>> ipaddress.IPv6Address('2001:db8::1000')
150 library/ipaddress :db8 '2001:db8::1000'
151 library/ipaddress :: '2001:db8::1000'
152 library/ipaddress 231 :db8 >>> f'{ipaddress.IPv6Address("2001:db8::1000"):s}'
153 library/ipaddress 231 :: >>> f'{ipaddress.IPv6Address("2001:db8::1000"):s}'
154 library/ipaddress :: IPv6Address('ff02::5678%1')
155 library/ipaddress :: fe80::1234
156 library/ipaddress :db8 >>> ipaddress.ip_address("2001:db8::1").reverse_pointer

View File

@ -537,6 +537,10 @@ Scoped IPv6 addresses can be parsed using :class:`ipaddress.IPv6Address`.
If present, scope zone ID is available through the :attr:`~ipaddress.IPv6Address.scope_id` attribute.
(Contributed by Oleksandr Pavliuk in :issue:`34788`.)
Starting with Python 3.9.5 the :mod:`ipaddress` module no longer
accepts any leading zeros in IPv4 address strings.
(Contributed by Christian Heimes in :issue:`36384`).
math
----
@ -1114,6 +1118,14 @@ Changes in the Python API
compatible classes that don't inherit from those mentioned types.
(Contributed by Roger Aiudi in :issue:`34775`).
* Starting with Python 3.9.5 the :mod:`ipaddress` module no longer
accepts any leading zeros in IPv4 address strings. Leading zeros are
ambiguous and interpreted as octal notation by some libraries. For example
the legacy function :func:`socket.inet_aton` treats leading zeros as octal
notatation. glibc implementation of modern :func:`~socket.inet_pton` does
not accept any leading zeros.
(Contributed by Christian Heimes in :issue:`36384`).
* :func:`codecs.lookup` now normalizes the encoding name the same way as
:func:`encodings.normalize_encoding`, except that :func:`codecs.lookup` also
converts the name to lower case. For example, ``"latex+latin1"`` encoding

View File

@ -1223,6 +1223,11 @@ class _BaseV4:
if len(octet_str) > 3:
msg = "At most 3 characters permitted in %r"
raise ValueError(msg % octet_str)
# Handle leading zeros as strict as glibc's inet_pton()
# See security bug bpo-36384
if octet_str != '0' and octet_str[0] == '0':
msg = "Leading zeros are not permitted in %r"
raise ValueError(msg % octet_str)
# Convert to integer (we know digits are legal)
octet_int = int(octet_str, 10)
if octet_int > 255:

View File

@ -96,10 +96,23 @@ class CommonTestMixin:
class CommonTestMixin_v4(CommonTestMixin):
def test_leading_zeros(self):
self.assertInstancesEqual("000.000.000.000", "0.0.0.0")
self.assertInstancesEqual("192.168.000.001", "192.168.0.1")
self.assertInstancesEqual("016.016.016.016", "16.16.16.16")
self.assertInstancesEqual("001.000.008.016", "1.0.8.16")
# bpo-36384: no leading zeros to avoid ambiguity with octal notation
msg = "Leading zeros are not permitted in '\d+'"
addresses = [
"000.000.000.000",
"192.168.000.001",
"016.016.016.016",
"192.168.000.001",
"001.000.008.016",
"01.2.3.40",
"1.02.3.40",
"1.2.03.40",
"1.2.3.040",
]
for address in addresses:
with self.subTest(address=address):
with self.assertAddressError(msg):
self.factory(address)
def test_int(self):
self.assertInstancesEqual(0, "0.0.0.0")

View File

@ -0,0 +1,6 @@
:mod:`ipaddress` module no longer accepts any leading zeros in IPv4 address
strings. Leading zeros are ambiguous and interpreted as octal notation by
some libraries. For example the legacy function :func:`socket.inet_aton`
treats leading zeros as octal notatation. glibc implementation of modern
:func:`~socket.inet_pton` does not accept any leading zeros. For a while
the :mod:`ipaddress` module used to accept ambiguous leading zeros.