Skip to content

A Series of Potential DoS Risk Points in the CPython Standard Library #144133

@kexinoh

Description

@kexinoh

Bug report

Bug description:

Approximately six months ago, our automated scanning program detected several issues and an issue(#134873) was filed. Recently, after improving the scanner and re-running it against CPython, additional locations were found that may be susceptible to algorithmic complexity attacks. Although each finding has been validated as carefully as possible, some false positives may still exist.
Please note that these findings do not necessarily imply an exploitable vulnerability (and are unlikely to represent a straightforward remote attack vector). After discussion with PSRC, these points are being disclosed in this issue in order to leverage community review and contributions to assess impact and, where appropriate, implement hardening or fixes.
Incremental updates will be posted over the coming weeks.

We’ve updated the items related to the email module in #136063.

  1. _c3_mro(EXP)

    cpython/Lib/functools.py

    Lines 780 to 823 in e66597d

    def _c3_mro(cls, abcs=None):
    """Computes the method resolution order using extended C3 linearization.
    If no *abcs* are given, the algorithm works exactly like the built-in C3
    linearization used for method resolution.
    If given, *abcs* is a list of abstract base classes that should be inserted
    into the resulting MRO. Unrelated ABCs are ignored and don't end up in the
    result. The algorithm inserts ABCs where their functionality is introduced,
    i.e. issubclass(cls, abc) returns True for the class itself but returns
    False for all its direct base classes. Implicit ABCs for a given class
    (either registered or inferred from the presence of a special method like
    __len__) are inserted directly after the last ABC explicitly listed in the
    MRO of said class. If two implicit ABCs end up next to each other in the
    resulting MRO, their ordering depends on the order of types in *abcs*.
    """
    for i, base in enumerate(reversed(cls.__bases__)):
    if hasattr(base, '__abstractmethods__'):
    boundary = len(cls.__bases__) - i
    break # Bases up to the last explicit ABC are considered first.
    else:
    boundary = 0
    abcs = list(abcs) if abcs else []
    explicit_bases = list(cls.__bases__[:boundary])
    abstract_bases = []
    other_bases = list(cls.__bases__[boundary:])
    for base in abcs:
    if issubclass(cls, base) and not any(
    issubclass(b, base) for b in cls.__bases__
    ):
    # If *cls* is the class that introduces behaviour described by
    # an ABC *base*, insert said ABC to its MRO.
    abstract_bases.append(base)
    for base in abstract_bases:
    abcs.remove(base)
    explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases]
    abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases]
    other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases]
    return _c3_merge(
    [[cls]] +
    explicit_c3_mros + abstract_c3_mros + other_c3_mros +
    [explicit_bases] + [abstract_bases] + [other_bases]
    )

2.allmethods(Exp)

def allmethods(cl):

3.FragmentBuilderNS._getNSattrs (Poly)

def _getNSattrs(self):
)

  1. __dict_replace(EXP)
    def __dict_replace(s, d):

5.punycode_decode(Poly)

def punycode_decode(text, errors):

.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions