Esempio n. 1
0
    def generate_intersects_from_pkg_node(self, pkg_node, tag=None):
        arch = pkg_node.get("arch")
        if arch is not None:
            arch = str(arch.strip()).split()
            if not arch or "*" in arch:
                arch = None

        vuln = list(pkg_node.findall("vulnerable"))
        if not vuln:
            return None
        elif len(vuln) > 1:
            vuln_list = [self.generate_restrict_from_range(x) for x in vuln]
            vuln = packages.OrRestriction(*vuln_list)
        else:
            vuln_list = [self.generate_restrict_from_range(vuln[0])]
            vuln = vuln_list[0]
        if arch is not None:
            vuln = packages.AndRestriction(
                vuln,
                packages.PackageRestriction(
                    "keywords", values.ContainmentMatch(all=False, *arch)))
        invuln = (pkg_node.findall("unaffected"))
        if not invuln:
            # wrap it.
            return packages.KeyedAndRestriction(vuln, tag=tag)
        invuln_list = [
            self.generate_restrict_from_range(x, negate=True) for x in invuln
        ]
        invuln = [x for x in invuln_list if x not in vuln_list]
        if not invuln:
            if tag is None:
                return packages.KeyedAndRestriction(vuln, tag=tag)
            return packages.KeyedAndRestriction(vuln, tag=tag)
        return packages.KeyedAndRestriction(vuln, tag=tag, *invuln)
Esempio n. 2
0
def parse_target(restriction, repo, installed_repos, return_none=False):
    """Use :obj:`parserestrict.parse_match` to produce a list of matches.

    This matches the restriction against a repo. If multiple pkgs match and a
    simple package name was provided, then the restriction is applied against
    installed repos. If multiple matches still exist then pkgs from the
    'virtual' category are skipped. If multiple pkgs still match the
    restriction, AmbiguousQuery is raised otherwise the matched atom is
    returned. On the other hand, if a globbed match was specified, all repo
    matches are returned.

    :param restriction: string to convert.
    :param repo: :obj:`pkgcore.repository.prototype.tree` instance to search in.
    :param installed_repos: :obj:`pkgcore.config.domain.all_installed_repos`
        instance to search in.
    :param return_none: indicates if no matches raises or returns C{None}

    :return: a list of matches or C{None}.
    """
    key_matches = {x.unversioned_atom for x in repo.itermatch(restriction)}
    if not key_matches:
        if return_none:
            return None
        raise NoMatches(restriction)
    elif len(key_matches) > 1:
        if any(isinstance(r, restricts.PackageDep) for r in iflatten_instance([restriction])):
            if len(restriction) > 1:
                # drop repo specific restrictions, ebuild repos don't match installed pkgs
                restriction = restriction.remove_restriction(
                    restriction_types=(restricts.RepositoryDep,))

            # find installed package matches
            matches = {x.unversioned_atom for x in installed_repos.itermatch(restriction)}

            # try removing stub pkgs if there are multiple installed matches or none at all
            skip_categories = {'acct-group', 'acct-user', 'virtual'}
            if not matches:
                matches = {x for x in key_matches if x.category not in skip_categories}
            elif len(matches) > 1:
                matches = {x for x in matches if x.category not in skip_categories}

            if len(matches) == 1:
                p = matches.pop()
                # TODO: collapse redundant restrictions?
                return [packages.KeyedAndRestriction(restriction, p, key=p.key)]

            raise AmbiguousQuery(restriction, sorted(key_matches))
        else:
            # if a glob was specified then just return every match
            return key_matches
    if isinstance(restriction, atom):
        # atom is guaranteed to be fine, since it's cat/pkg
        return [restriction]
    return [packages.KeyedAndRestriction(restriction, key=key_matches.pop().key)]
Esempio n. 3
0
 def __iter__(self):
     for glsa, matches in find_vulnerable_repo_pkgs(self.glsa_src,
                                                    self.vdb,
                                                    grouped=True,
                                                    arch=self.arch):
         yield packages.KeyedAndRestriction(glsa[0],
                                            restriction.Negate(glsa[1]))
Esempio n. 4
0
    def insert_blockers(self, stack, choices, blocks):
        # level blockers.
        was_livefs = choices.current_pkg.repo.livefs
        for x in blocks:
            if not was_livefs:
                self._ensure_livefs_is_loaded(x)

            rewrote_blocker = self.generate_mangled_blocker(choices, x)
            l = self.state.add_blocker(choices, rewrote_blocker, key=x.key)
            if l:
                # blocker caught something. yay.
                self._dprint("%s blocker %s hit %s for atom %s pkg %s",
                             (stack[-1].mode, x, l, stack[-1].atom,
                              choices.current_pkg))
                if x.weak_blocker:
                    # note that we use the top frame of the stacks' dbs; this
                    # is to allow us to upgrade as needed.
                    # For this to match, it's *only* possible if the blocker is resolved
                    # since the limiter is already in place.
                    result = self._rec_add_atom(
                        packages.KeyedAndRestriction(restriction.Negate(x),
                                                     _atom.atom(x.key),
                                                     key=x.key), stack,
                        stack[0].dbs)
                    if not result:
                        # ok, inserted a new version.  did it take care of the conflict?
                        # it /may/ not have, via filling a different slot...
                        result = self.state.match_atom(x)
                        if not result:
                            # ignore the blocker, we resolved past it.
                            continue
                return x, l
        return None
Esempio n. 5
0
def parse_atom(restriction, repo, livefs_repos, return_none=False):
    """Use :obj:`parserestrict.parse_match` to produce a single atom.

    This matches the restriction against a repo. If multiple pkgs match, then
    the restriction is applied against installed repos skipping pkgs from the
    'virtual' category. If multiple pkgs still match the restriction,
    AmbiguousQuery is raised otherwise the matched atom is returned.

    :param restriction: string to convert.
    :param repo: :obj:`pkgcore.repository.prototype.tree` instance to search in.
    :param livefs_repos: :obj:`pkgcore.config.domain.all_livefs_repos` instance to search in.
    :param return_none: indicates if no matches raises or returns C{None}

    :return: an atom or C{None}.
    """
    key_matches = set(x.key for x in repo.itermatch(restriction))
    if not key_matches:
        raise NoMatches(restriction)
    elif len(key_matches) > 1:
        installed_matches = set(x.key
                                for x in livefs_repos.itermatch(restriction)
                                if x.category != 'virtual')
        if len(installed_matches) == 1:
            restriction = atom(installed_matches.pop())
        else:
            raise AmbiguousQuery(restriction, sorted(key_matches))
    if isinstance(restriction, atom):
        # atom is guaranteed to be fine, since it's cat/pkg
        return restriction
    return packages.KeyedAndRestriction(restriction, key=key_matches.pop())
Esempio n. 6
0
 def add_atoms(self, restricts, **kwds):
     restricts = [
         packages.KeyedAndRestriction(self._vdb_restriction,
                                      x,
                                      key=x.key) for x in restricts
     ]
     return self.overriding_resolver_kls.add_atoms(
         self, restricts, **kwds)
Esempio n. 7
0
def parse_target(restriction, repo, livefs_repos, return_none=False):
    """Use :obj:`parserestrict.parse_match` to produce a list of matches.

    This matches the restriction against a repo. If multiple pkgs match and a
    simple package name was provided, then the restriction is applied against
    installed repos. If multiple matches still exist then pkgs from the
    'virtual' category are skipped. If multiple pkgs still match the
    restriction, AmbiguousQuery is raised otherwise the matched atom is
    returned. On the other hand, if a globbed match was specified, all repo
    matches are returned.

    :param restriction: string to convert.
    :param repo: :obj:`pkgcore.repository.prototype.tree` instance to search in.
    :param livefs_repos: :obj:`pkgcore.config.domain.all_livefs_repos` instance to search in.
    :param return_none: indicates if no matches raises or returns C{None}

    :return: a list of matches or C{None}.
    """
    key_matches = {x.key for x in repo.itermatch(restriction)}
    if not key_matches:
        if return_none:
            return None
        raise NoMatches(restriction)
    elif len(key_matches) > 1:
        if any(
                isinstance(r, restricts.PackageDep)
                for r in iflatten_instance([restriction])):
            if len(restriction) > 1:
                # drop repo specific restrictions, ebuild repos will not match installed (vdb) repo
                restriction = restriction.remove_restriction(
                    restriction_types=(restricts.RepositoryDep, ))
            # check for installed package matches
            installed_matches = {
                x.key
                for x in livefs_repos.itermatch(restriction)
            }
            if len(installed_matches) > 1:
                # try removing virtuals if there are multiple matches
                installed_matches = {
                    x
                    for x in installed_matches if not x.startswith('virtual/')
                }
            if len(installed_matches) == 1:
                return [atom(installed_matches.pop())]
            raise AmbiguousQuery(restriction, sorted(key_matches))
        else:
            # if a glob was specified then just return every match
            return [atom(x) for x in key_matches]
    if isinstance(restriction, atom):
        # atom is guaranteed to be fine, since it's cat/pkg
        return [restriction]
    return [packages.KeyedAndRestriction(restriction, key=key_matches.pop())]
Esempio n. 8
0
    def pkg_grouped_iter(self, sorter=None):
        """yield GLSA restrictions grouped by package key

        :param sorter: must be either None, or a comparison function
        """

        if sorter is None:
            sorter = iter
        pkgs = {}
        pkgatoms = {}
        for glsa, pkg, pkgatom, vuln in self.iter_vulnerabilities():
            pkgatoms[pkg] = pkgatom
            pkgs.setdefault(pkg, []).append(vuln)

        for pkgname in sorter(pkgs):
            yield packages.KeyedAndRestriction(
                pkgatoms[pkgname], packages.OrRestriction(*pkgs[pkgname]), key=pkgname)
Esempio n. 9
0
def parse_target(restriction, repo, livefs_repos, return_none=False):
    """Use :obj:`parserestrict.parse_match` to produce a list of matches.

    This matches the restriction against a repo. If multiple pkgs match and a
    simple package name was provided, then the restriction is applied against
    installed repos skipping pkgs from the 'virtual' category. If multiple pkgs
    still match the restriction, AmbiguousQuery is raised otherwise the matched
    atom is returned. On the other hand, if a globbed match was specified, all
    repo matches are returned.

    :param restriction: string to convert.
    :param repo: :obj:`pkgcore.repository.prototype.tree` instance to search in.
    :param livefs_repos: :obj:`pkgcore.config.domain.all_livefs_repos` instance to search in.
    :param return_none: indicates if no matches raises or returns C{None}

    :return: a list of matches or C{None}.
    """
    key_matches = set(x.key for x in repo.itermatch(restriction))
    if not key_matches:
        if return_none:
            return None
        else:
            raise NoMatches(restriction)
    elif len(key_matches) > 1:
        if isinstance(restriction, restricts.PackageDep):
            # check for installed package name matches
            installed_matches = set(
                x.key for x in livefs_repos.itermatch(restriction)
                if x.category != 'virtual')
            if len(installed_matches) == 1:
                return [atom(installed_matches.pop())]
            else:
                raise AmbiguousQuery(restriction, sorted(key_matches))
        else:
            # if a glob was specified then just return every match
            return [atom(x) for x in key_matches]
    if isinstance(restriction, atom):
        # atom is guaranteed to be fine, since it's cat/pkg
        return [restriction]
    return [packages.KeyedAndRestriction(restriction, key=key_matches.pop())]
Esempio n. 10
0
 def __iter__(self):
     for glsa, catpkg, pkgatom, vuln in self.iter_vulnerabilities():
         yield packages.KeyedAndRestriction(pkgatom,
                                            vuln,
                                            key=catpkg,
                                            tag="GLSA vulnerable:")