python / python/cpython

IPv6Address ordering is scope-id-blind, breaking trichotomy and making sorted()/min()/max() non-deterministic for scoped addresses

Đang mở
#151,769 2 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

3.14 3.15 3.16 stdlib type-bug
Ngôn ngữ chính
Python
Star
77.2k
Fork
36k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

Bug report

Bug description:

COMPONENT: Library (Lib/ipaddress.py)

AFFECTED VERSIONS: main (3.16.0a0) and 3.14 (reproduced on 3.14.6). The defect dates to when scope_id was added to IPv6Address.__eq__/__hash__/__str__ but not to ordering.

SUMMARY

IPv6Address.__eq__ and __hash__ fold in the interface scope_id (so fe80::1 and fe80::1%eth0 are unequal and hash differently), but IPv6Address does not override ordering — it inherits _BaseAddress.__lt__, which compares only the integer address and ignores _scope_id. _BaseAddress is decorated with @functools.total_ordering, which synthesizes __gt__/__le__/__ge__ from __lt__ and __eq__. The synthesized __gt__ is effectively not (a < b) and a != b. For two addresses with the same integer but different scope, a < b is False (scope-blind __lt__) while a != b is True (scope-aware __eq__), so a > b is True — and symmetrically b > a is also True. The relation is not a strict order: trichotomy and antisymmetry both fail, and sorting is non-deterministic.

MINIMAL REPRODUCTION

>>> import ipaddress
>>> a = ipaddress.ip_address('fe80::1')
>>> b = ipaddress.ip_address('fe80::1%eth0')
>>> a == b
False
>>> a > b
True
>>> b > a            # antisymmetry violated: both directions are "greater"
True

>>> from itertools import permutations
>>> items = [ipaddress.ip_address(s)
...          for s in ('fe80::1', 'fe80::1%eth0', 'fe80::1%eth1')]
>>> {tuple(str(x) for x in sorted(p)) for p in permutations(items)}
# 6 DISTINCT outputs — sorted() just returns the input order

ROOT CAUSE

scope_id was added to IPv6Address.__eq__/__hash__/__str__ but not to ordering, and IPv6Address defines no __lt__. The @functools.total_ordering operators on _BaseAddress dispatch through type(self).__lt__, which (absent an override) resolves to the scope-blind _BaseAddress.__lt__ while total_ordering also consults the scope-aware __eq__ — so they disagree. The functools docs note total_ordering "makes no attempt to override methods declared in the class or its superclasses," which is exactly why the subclass inherits a __lt__ inconsistent with its own __eq__.

The minimal fix is a scope-aware IPv6Address.__lt__ (tie-break on scope_id only when the integer address is equal; unscoped sorts before scoped; scope ids compare lexicographically). Because the derived operators dispatch through type(self).__lt__, overriding only __lt__ on the subclass routes all four comparisons through the scope-aware path. This also transitively repairs scoped IPv6Interface and IPv6Network ordering, which delegate to address comparison. _BaseAddress.__lt__ is untouched, so IPv4Address is unaffected.

RELATION TO CONCURRENT WORK (#141647 / PR #141842) — please don't close as a dup

There is concurrent activity in gh-141647 / PR gh-141842 touching the comparison dunders, but it is orthogonal: that PR's rewritten _BaseAddress.__lt__ stays scope-blind (return self._ip < other._ip) and adds no IPv6Address override, and its test_mixed_type_ordering skips same-type pairs, so this same-type scoped trichotomy failure survives that PR untested. This fix adds a scope-aware override on the IPv6Address subclass only and does not modify _BaseAddress.__lt__, so it composes cleanly regardless of merge order (or could be folded into #141842).

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs
  • gh-151772
  • gh-151864
  • gh-152320

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu trong Lib/ipaddress.py với các phương thức so sánh của IPv6Address và tái hiện các ví dụ về scoped addresses từ issue. Xác nhận rằng thứ tự là xác định và nhất quán đối với scoped addresses, trong khi IPv4Address và các phép so sánh liên quan của IPv6Interface và IPv6Network không bị ảnh hưởng.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
networking
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
35/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.