Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolver.py/ThreadResolver: address[3] does not exist #5901

Closed
1 task done
dilyanpalauzov opened this issue Jul 19, 2021 · 3 comments
Closed
1 task done

resolver.py/ThreadResolver: address[3] does not exist #5901

dilyanpalauzov opened this issue Jul 19, 2021 · 3 comments
Labels
bug reproducer: missing This PR or issue lacks code, which reproduce the problem described or clearly understandable STR

Comments

@dilyanpalauzov
Copy link

Describe the bug

As outlined at pimutils/vdirsyncer#916, I use python 3.8 with aiohttp 3.8 branch (v3.7.4.post0-209-g22f8be99) . In aiohttp/resolver.py:ThreadedResolver the line

if family == socket.AF_INET6 and address[3]: # type: ignore[misc]

fails, as address has only two elements and address[3] is out of range.

The values of adress are:

AddressFamily.AF_INET ('142.250.185.238', 443)
AddressFamily.AF_INET6 (10, b'\x01\xbb\x00\x00\x00\x00*\x00\x14P@\x01\x08\x13')

The system is not connected to IPv6, no routes, no iPv6 addressese etc, but the kernel understands IPv6. I fixed it locally with:

diff --git a/aiohttp/resolver.py b/aiohttp/resolver.py
index 2161c8fa..4e57b319 100644
--- a/aiohttp/resolver.py
+++ b/aiohttp/resolver.py
@@ -38,16 +38,7 @@ class ThreadedResolver(AbstractResolver):
 
         hosts = []
         for family, _, proto, _, address in infos:
-            if family == socket.AF_INET6 and address[3]:  # type: ignore[misc]
-                # This is essential for link-local IPv6 addresses.
-                # LL IPv6 is a VERY rare case. Strictly speaking, we should use
-                # getnameinfo() unconditionally, but performance makes sense.
-                host, _port = socket.getnameinfo(
-                    address, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV
-                )
-                port = int(_port)
-            else:
-                host, port = address[:2]
+            host, port = address[:2]
             hosts.append(
                 {
                     "hostname": hostname,

To Reproduce

See above.

Expected behavior

Shall not read address[3], when address[3] does not exist.

Logs/tracebacks

Not applicable.

Python Version

$ python --version

Python 3.8.8+

aiohttp Version

$ python -m pip show aiohttp

3.8.0a0

multidict Version

$ python -m pip show multidict
5.1.0

yarl Version

$ python -m pip show yarl

1.6.3

OS

Linux from Scratch, python 3.8.8+

Related component

Client

Additional context

No response

Code of Conduct

  • I agree to follow the aio-libs Code of Conduct
@Hanaasagi
Copy link
Member

resolve use the getaddrinfo to get the socket infomation.

async def resolve(
self, hostname: str, port: int = 0, family: int = socket.AF_INET
) -> List[Dict[str, Any]]:
infos = await self._loop.getaddrinfo(
hostname,
port,
type=socket.SOCK_STREAM,
family=family,
flags=socket.AI_ADDRCONFIG,
)
hosts = []
for family, _, proto, _, address in infos:

From the Python doc, the sockaddr part of getaddrinfo function' return value is a 4-tuple if the family is AF_INET6.

The function returns a list of 5-tuples with the following structure:

(family, type, proto, canonname, sockaddr)

In these tuples, family, type, proto are all integers and are meant to be passed to the socket() function. canonname will be a string representing the canonical name of the host if AI_CANONNAME is part of the flags argument; else canonname will be empty. sockaddr is a tuple describing a socket address, whose format depends on the returned family (a (address, port) 2-tuple for AF_INET, a (address, port, flow info, scope id) 4-tuple for AF_INET6), and is meant to be passed to the socket.connect() method.

The behavior is strange, not as stated in the doc. 😕

Ref: https://docs.python.org/3.8/library/socket.html#socket.getaddrinfo

@webknjaz
Copy link
Member

webknjaz commented Jul 19, 2021

The behavior is strange, not as stated in the doc.

IIRC, it returns the structure from the underlying kernel syscall. FWIW I think this has been fixed by #5176 on master, 3.8 and 3.7.

@webknjaz
Copy link
Member

webknjaz commented Jul 19, 2021

Duplicate of #5156. Please post any other observations or/and a reproducer there.

@webknjaz webknjaz added the reproducer: missing This PR or issue lacks code, which reproduce the problem described or clearly understandable STR label Jul 19, 2021
@aio-libs aio-libs locked as resolved and limited conversation to collaborators Jul 19, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug reproducer: missing This PR or issue lacks code, which reproduce the problem described or clearly understandable STR
Projects
None yet
Development

No branches or pull requests

3 participants