§
    íóÉj&  ã                   óX   — d Z ddlZg d¢ZdZ e¦   «         Z G d„ d¦  «        Zdefd„ZdS )a
  
A wall-clock backstop for NLTK code paths that compile *caller-supplied*
regular expressions or tag patterns.

Several public APIs accept a pattern from the caller and run it over
(possibly attacker-controlled) text:

* :class:`nltk.tokenize.RegexpTokenizer` / ``regexp_tokenize`` -- ``pattern``
* :class:`nltk.tag.RegexpTagger` -- the ``regexp`` of each ``(regexp, tag)`` pair
* :func:`nltk.tgrep.tgrep_compile` -- the ``/regex/`` node literal in a query
* :class:`nltk.chunk.regexp.RegexpChunkRule` and its ``ChunkRule`` / ``StripRule``
  / ``UnChunkRule`` / ``MergeRule`` / ``SplitRule`` subclasses -- the tag pattern

A crafted pattern (e.g. ``(a+)+$`` or ``(a|a)*$``) can trigger catastrophic
backtracking and pin a CPU core indefinitely -- a denial of service
(CWE-1333). This module centralises a single, tested defence used by all of
those sinks, in two layers:

1. **Compile with the third-party ``regex`` engine** instead of the stdlib
   ``re``. Its optimiser collapses a large class of catastrophic patterns
   -- notably nested quantifiers over the *same* sub-expression such as
   ``(a+)+$`` -- to linear time outright, so those "attacks" finish in
   microseconds and never reach the timeout.

2. **Run every match under a wall-clock ``timeout``**. The optimiser does *not*
   cover every shape -- an alternation of identical branches such as
   ``(a|a)*`` (and the equivalent ``<a|a>*`` chunk tag pattern) still
   backtracks exponentially in *both* ``re`` and ``regex``. The timeout is
   therefore a *mandatory* backstop, not a nicety: when it trips, an
   actionable :class:`TimeoutError` is raised instead of hanging the process.

Rewriting the pattern to be linear (atomic groups / possessive quantifiers)
was evaluated and rejected: it does *not* defuse the identical-branch
alternation, and it silently changes match semantics for legitimate greedy
patterns such as ``<.*>*<NN>``. A bounded timeout is the only defence that is
both complete and behaviour-preserving for arbitrary caller patterns.

Usage::

    from nltk import redos
    rx = redos.compile(pattern, flags)      # -> a TimedPattern
    rx.findall(text)                         # runs under DEFAULT_TIMEOUT
    rx.search(text, timeout=1.0)             # per-call override

``TimedPattern`` quacks like the subset of ``re.Pattern`` these sinks use
(``findall`` / ``finditer`` / ``split`` / ``search`` / ``match`` / ``fullmatch``
/ ``sub`` / ``subn`` plus attribute access such as ``.pattern`` and ``.flags``),
so it is a drop-in replacement for a compiled pattern at those call sites.
é    N)ÚDEFAULT_TIMEOUTÚTimedPatternÚcompileg      @c                   ó¤   — e Zd ZdZdZefd„Zd„ Zd„ Zedœd„Z	edœd„Z
edœd	„Zedœd
„Zedœd„Zedœd„Zedœd„Zedœd„Zd„ Zd„ Zd„ Zd„ ZdS )r   aÛ  A compiled :mod:`regex` pattern whose match operations are bounded by a
    wall-clock timeout.

    Every exposed match method runs the underlying engine with ``timeout=`` and
    re-raises a bare :class:`TimeoutError` as an actionable one naming the
    offending pattern. Any other attribute (``pattern``, ``flags``, ``groups``,
    ``groupindex``, ...) is delegated to the wrapped pattern, so instances are a
    drop-in for a compiled pattern at NLTK's regex sinks.
    ©Ú_rxÚ_timeoutc                 ó"   — || _         || _        d S ©Nr   )ÚselfÚcompiledÚtimeouts      úm/home/lighthouse/badge-speaker-benchmark/.benchmark-venv-community/lib/python3.11/site-packages/nltk/redos.pyÚ__init__zTimedPattern.__init__Z   s   € ØˆŒØˆŒˆˆó    c                 óF   — |t           u r| j        }|t           u rt          }|S r   )Ú_UNSETr	   r   ©r   r   s     r   Ú_resolvezTimedPattern._resolve`   s)   € Ø•fÐÐØ”mˆGØ•fÐÐÝ%ˆGØˆr   c                 óB   — t          d|› d| j        j        ›d�¦  «        S )Nz&regular-expression match exceeded its zs time limit; the pattern z† may be pathological for this input (catastrophic backtracking / ReDoS). Pass timeout=None to disable the limit for a trusted pattern.)ÚTimeoutErrorr   Úpatternr   s     r   Ú_failzTimedPattern._failg   s<   € Ýð0°Wð 0ð 0Ø”xÔ'ð0ð 0ð 0ñ
ô 
ð 	
r   )r   c                ó¦   — |                       |¦  «        }	  | j        j        |g|¢R d|i|¤ŽS # t          $ r |                      |¦  «        d ‚w xY w©Nr   )r   r   Úsearchr   r   ©r   Ústringr   ÚargsÚkwargsÚts         r   r   zTimedPattern.searchq   sn   € Ø�MŠM˜'Ñ"Ô"ˆð	*Ø"�4”8”? 6ÐF¨DÐFÐFÐF¸!ÐF¸vÐFÐFÐFøÝð 	*ð 	*ð 	*Ø—*’*˜Q‘-”- TÐ)ð	*øøøó	   —/ ¯!Ac                ó¦   — |                       |¦  «        }	  | j        j        |g|¢R d|i|¤ŽS # t          $ r |                      |¦  «        d ‚w xY wr   )r   r   Úmatchr   r   r   s         r   r$   zTimedPattern.matchx   ón   € Ø�MŠM˜'Ñ"Ô"ˆð	*Ø!�4”8”> &ÐE¨4ÐEÐEÐE¸ÐE¸fÐEÐEÐEøÝð 	*ð 	*ð 	*Ø—*’*˜Q‘-”- TÐ)ð	*øøør"   c                ó¦   — |                       |¦  «        }	  | j        j        |g|¢R d|i|¤ŽS # t          $ r |                      |¦  «        d ‚w xY wr   )r   r   Ú	fullmatchr   r   r   s         r   r'   zTimedPattern.fullmatch   so   € Ø�MŠM˜'Ñ"Ô"ˆð	*Ø%�4”8Ô% fÐI¨tÐIÐIÐI¸QÐIÀ&ÐIÐIÐIøÝð 	*ð 	*ð 	*Ø—*’*˜Q‘-”- TÐ)ð	*øøør"   c                ó¦   — |                       |¦  «        }	  | j        j        |g|¢R d|i|¤ŽS # t          $ r |                      |¦  «        d ‚w xY wr   )r   r   Úfindallr   r   r   s         r   r)   zTimedPattern.findall†   so   € Ø�MŠM˜'Ñ"Ô"ˆð	*Ø#�4”8Ô# FÐG¨TÐGÐGÐG¸1ÐGÀÐGÐGÐGøÝð 	*ð 	*ð 	*Ø—*’*˜Q‘-”- TÐ)ð	*øøør"   c                ó¦   — |                       |¦  «        }	  | j        j        |g|¢R d|i|¤ŽS # t          $ r |                      |¦  «        d ‚w xY wr   )r   r   Úsplitr   r   r   s         r   r+   zTimedPattern.split�   r%   r"   c                ó¨   — |                       |¦  «        }	  | j        j        ||g|¢R d|i|¤ŽS # t          $ r |                      |¦  «        d ‚w xY wr   )r   r   Úsubr   r   ©r   Úreplr   r   r   r    r!   s          r   r-   zTimedPattern.sub”   sp   € Ø�MŠM˜'Ñ"Ô"ˆð	*Ø�4”8”<  fÐI¨tÐIÐIÐI¸QÐIÀ&ÐIÐIÐIøÝð 	*ð 	*ð 	*Ø—*’*˜Q‘-”- TÐ)ð	*øøøó	   —0 °!Ac                ó¨   — |                       |¦  «        }	  | j        j        ||g|¢R d|i|¤ŽS # t          $ r |                      |¦  «        d ‚w xY wr   )r   r   Úsubnr   r   r.   s          r   r2   zTimedPattern.subn›   sp   € Ø�MŠM˜'Ñ"Ô"ˆð	*Ø �4”8”=  vÐJ°ÐJÐJÐJ¸aÐJÀ6ÐJÐJÐJøÝð 	*ð 	*ð 	*Ø—*’*˜Q‘-”- TÐ)ð	*øøør0   c             /   óº   K  — |                       |¦  «        }	  | j        j        |g|¢R d|i|¤ŽE d {V —† d S # t          $ r |                      |¦  «        d ‚w xY wr   )r   r   Úfinditerr   r   r   s         r   r4   zTimedPattern.finditer¢   s�   è è € ð �MŠM˜'Ñ"Ô"ˆð	*Ø(�t”xÔ(¨ÐL°$ÐLÐLÐLÀÐLÀVÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLøÝð 	*ð 	*ð 	*Ø—*’*˜Q‘-”- TÐ)ð	*øøøs	   ™9 ¹!Ac                 óž   — |                      d¦  «        r$|                     d¦  «        rt          |¦  «        ‚t          | j        |¦  «        S )NÚ__)Ú
startswithÚendswithÚAttributeErrorÚgetattrr   )r   Únames     r   Ú__getattr__zTimedPattern.__getattr__­   sK   € ð �?Š?˜4Ñ Ô ð 	' T§]¢]°4Ñ%8Ô%8ð 	'Ý  Ñ&Ô&Ð&Ý�t”x Ñ&Ô&Ð&r   c                 óÂ   — t          |t          ¦  «        st          S | j        j        |j        j        k    o)| j        j        |j        j        k    o| j        |j        k    S r   )Ú
isinstancer   ÚNotImplementedr   r   Úflagsr	   )r   Úothers     r   Ú__eq__zTimedPattern.__eq__µ   sY   € õ ˜%¥Ñ.Ô.ð 	"Ý!Ð!àŒHÔ ¤	Ô 1Ò1ð 0Ø”” %¤)¤/Ò1ð0à” ¤Ò/ð	
r   c                 óX   — t          | j        j        | j        j        | j        f¦  «        S r   )Úhashr   r   r@   r	   ©r   s    r   Ú__hash__zTimedPattern.__hash__Ã   s"   € Ý�T”XÔ% t¤x¤~°t´}ÐEÑFÔFÐFr   c                 ó2   — d| j         j        ›d| j        ›d�S )NzTimedPattern(z
, timeout=ú))r   r   r	   rE   s    r   Ú__repr__zTimedPattern.__repr__Æ   s"   € ØO˜tœxÔ/ÐOÐO¸T¼]ÐOÐOÐOÐOr   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r   r   r   r   r   r$   r'   r)   r+   r-   r2   r4   r<   rB   rF   rI   © r   r   r   r   M   sŽ  € € € € € ðð ð $€Ià)/ð  ð  ð  ð  ðð ð ð
ð 
ð 
ð -3ð *ð *ð *ð *ð *ð ,2ð *ð *ð *ð *ð *ð 06ð *ð *ð *ð *ð *ð .4ð *ð *ð *ð *ð *ð ,2ð *ð *ð *ð *ð *ð 06ð *ð *ð *ð *ð *ð 17ð *ð *ð *ð *ð *ð /5ð *ð *ð *ð *ð *ð'ð 'ð 'ð
ð 
ð 
ðGð Gð GðPð Pð Pð Pð Pr   r   c                 óØ   — t          | t          ¦  «        r |t          u r| S t          | j        |¦  «        S t	          | d| ¦  «        }t          j        ||¦  «        }t          ||¦  «        S )a½  Compile ``pattern`` with the :mod:`regex` engine and wrap it so every
    match runs under a wall-clock timeout.

    :param pattern: a regular-expression string, or an already-compiled
        ``re``/``regex`` pattern (its ``.pattern`` is re-compiled with
        ``regex``), or an existing :class:`TimedPattern` (returned as-is with
        the requested timeout).
    :param flags: regex flags (stdlib ``re`` flag constants are accepted).
    :param timeout: default wall-clock limit for matches on the returned
        pattern; ``None`` disables it. Omit to use :data:`DEFAULT_TIMEOUT` at
        match time (so a later change to that module attribute still applies).
    :rtype: TimedPattern
    r   )r>   r   r   r   r:   Úregexr   )r   r@   r   Úsrcr   s        r   r   r   Ê   sj   € õ �'�<Ñ(Ô(ð 2Ø•fÐÐØˆNÝ˜GœK¨Ñ1Ô1Ð1å
�'˜9 gÑ
.Ô
.€CÝŒ}˜S %Ñ(Ô(€HÝ˜ 'Ñ*Ô*Ð*r   )rM   rQ   Ú__all__r   Úobjectr   r   r   rO   r   r   ú<module>rU      s˜   ðð0ð 0ðd €€€à
8Ð
8Ð
8€ð €ð
 
ˆ‰Œ€ðzPð zPð zPð zPð zPñ zPô zPð zPðz  fð +ð +ð +ð +ð +ð +r   