From c54c1af789b306a85e9d7e79fb54f02a05346616 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 13 Oct 2010 19:30:40 -0700 Subject: [PATCH] Bug #340899 - Validate getaddrinfo() results. --- pym/_emerge/actions.py | 29 +++++++++++++++++------- pym/_emerge/sync/getaddrinfo_validate.py | 29 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 pym/_emerge/sync/getaddrinfo_validate.py diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py index 86e6a529f..186e508f7 100644 --- a/pym/_emerge/actions.py +++ b/pym/_emerge/actions.py @@ -59,6 +59,7 @@ from _emerge.Scheduler import Scheduler from _emerge.search import search from _emerge.SetArg import SetArg from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice +from _emerge.sync.getaddrinfo_validate import getaddrinfo_validate from _emerge.sync.old_tree_timestamp import old_tree_timestamp_warn from _emerge.unmerge import unmerge from _emerge.UnmergeDepPriority import UnmergeDepPriority @@ -2096,34 +2097,46 @@ def action_sync(settings, trees, mtimedb, myopts, myaction): ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts): family = socket.AF_INET6 + addrinfos = None uris = [] try: - addrinfos = socket.getaddrinfo(hostname, None, - family, socket.SOCK_STREAM) + addrinfos = getaddrinfo_validate( + socket.getaddrinfo(hostname, None, + family, socket.SOCK_STREAM)) except socket.error as e: - writemsg("!!! getaddrinfo failed for '%s': %s\n" % (hostname, e), noiselevel=-1) + writemsg_level( + "!!! getaddrinfo failed for '%s': %s\n" % (hostname, e), + noiselevel=-1, level=logging.ERROR) + + if not addrinfos: # With some configurations we need to use the plain hostname # rather than try to resolve the ip addresses (bug #340817). uris.append(syncuri) else: + + AF_INET = socket.AF_INET + AF_INET6 = None + if socket.has_ipv6: + AF_INET6 = socket.AF_INET6 + ips_v4 = [] ips_v6 = [] for addrinfo in addrinfos: - if socket.has_ipv6 and addrinfo[0] == socket.AF_INET6: + if addrinfo[0] == AF_INET: + ips_v4.append("%s" % addrinfo[4][0]) + elif AF_INET6 is not None and addrinfo[0] == AF_INET6: # IPv6 addresses need to be enclosed in square brackets ips_v6.append("[%s]" % addrinfo[4][0]) - else: - ips_v4.append(addrinfo[4][0]) random.shuffle(ips_v4) random.shuffle(ips_v6) # Give priority to the address family that # getaddrinfo() returned first. - if socket.has_ipv6 and addrinfos and \ - addrinfos[0][0] == socket.AF_INET6: + if AF_INET6 is not None and addrinfos and \ + addrinfos[0][0] == AF_INET6: ips = ips_v6 + ips_v4 else: ips = ips_v4 + ips_v6 diff --git a/pym/_emerge/sync/getaddrinfo_validate.py b/pym/_emerge/sync/getaddrinfo_validate.py new file mode 100644 index 000000000..5e6009c74 --- /dev/null +++ b/pym/_emerge/sync/getaddrinfo_validate.py @@ -0,0 +1,29 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import sys + +if sys.hexversion >= 0x3000000: + basestring = str + +def getaddrinfo_validate(addrinfos): + """ + Validate structures returned from getaddrinfo(), + since they may be corrupt, especially when python + has IPv6 support disabled (bug #340899). + """ + valid_addrinfos = [] + for addrinfo in addrinfos: + try: + if len(addrinfo) != 5: + continue + if len(addrinfo[4]) < 2: + continue + if not isinstance(addrinfo[4][0], basestring): + continue + except TypeError: + continue + + valid_addrinfos.append(addrinfo) + + return valid_addrinfos -- 2.26.2