§
    íóÉj6  ã                   ó¦   — d Z ddlZddlmZ ddlmZ g d¢Z	 ddlmZ ddl	m
Z ddl	mZ d	Zn# e$ r d
Z G d„ de¦  «        ZY nw xY wd„ Zd„ Z
d„ ZdS )aO
  XML parsing helpers that refuse entity declarations.

``xml.etree.ElementTree`` honours ``<!ENTITY>`` declarations in a document's
internal DTD subset, so a small file can expand to an arbitrarily large string
in memory -- the "billion laughs" / entity-expansion DoS (CWE-776).  A 330-byte
document expands to a megabyte with five levels of nesting, and each further
level multiplies by ten.

libexpat 2.6.0 (2024) added an input-amplification cap, but it only engages
above an activation threshold (~8 MiB of output by default) and belongs to
whatever libexpat the running interpreter links -- not to NLTK.  Builds against
an older system libexpat have no cap at all.  These helpers make the guarantee
NLTK's own.

:func:`parse` and :func:`fromstring` use ``defusedxml`` when it is installed and
fall back to an equivalent standard-library implementation when it is not, so
NLTK is protected either way and ``defusedxml`` stays an optional dependency.

External entities are *not* the concern here -- ``ElementTree`` does not resolve
them (it reports ``undefined entity``) -- but the fallback rejects them too, for
parity with ``defusedxml``'s ``forbid_external`` default.

What is rejected
----------------
Any document that *declares* an entity (general or parameter) or references an
external one.  A DOCTYPE that merely names an external DTD (``<!DOCTYPE corpus
SYSTEM "apf.dtd">``) is *allowed*, because real corpora use them and
ElementTree never fetches the external subset anyway.  The five predefined XML
entities (``&amp;`` ``&lt;`` ``&gt;`` ``&quot;`` ``&apos;``) and numeric
character references need no declaration and keep working.  Both back ends agree
on this policy.

Why the fallback re-parses with expat instead of screening text
---------------------------------------------------------------
An earlier fallback screened the DOCTYPE internal subset with string walking.
That is a parser *differential* waiting to happen: a ``<!ENTITY`` hidden behind
a comment or processing instruction that the screener skips but expat still
processes slips through.  Re-parsing with :mod:`xml.parsers.expat` -- the very
library ``ElementTree`` sits on -- removes the differential entirely: whatever
declaration the real parse would act on, the pre-scan sees first and rejects.
The document is parsed once by expat to screen it and once by ElementTree to
build the tree; the extra pass only runs when ``defusedxml`` is absent.
(``defusedxml`` avoids the second pass by hooking ElementTree's own parser, but
only reaches it through global ``sys.modules`` surgery; the fallback keeps the
default C parser and touches no global state.)
é    N)ÚElementTree)Úexpat)ÚHAVE_DEFUSEDXMLÚEntitiesForbiddenÚ
fromstringÚparse©r   )r   )r   TFc                   ó$   ‡ — e Zd ZdZdˆ fd„	Zˆ xZS )r   zÝRaised when a document declares or references an XML entity.

        Mirrors ``defusedxml.common.EntitiesForbidden``, which is likewise a
        ``ValueError``, so ``except ValueError`` catches either back end.
        Ú c                 ód   •— || _         t          ¦   «                              d|pd› d�¦  «         d S )Nz"XML entity declaration forbidden: z	<unnamed>z{. Entity expansion can exhaust memory (CWE-776); if this document is trusted, parse it with xml.etree.ElementTree directly.)ÚnameÚsuperÚ__init__)Úselfr   ÚargsÚ	__class__s      €ún/home/lighthouse/badge-speaker-benchmark/.benchmark-venv-community/lib/python3.11/site-packages/nltk/xmlsec.pyr   zEntitiesForbidden.__init__K   sK   ø€ ØˆDŒIÝ‰GŒG×Òð°TÐ5H¸[ð ð ð ñô ð ð ð ó    )r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ú__classcell__)r   s   @r   r   r   D   sG   ø€ € € € € ð	ð 	ð	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	r   r   c                 ó®   — t          j        ¦   «         }d„ }d„ }||_        ||_        	 |                     | d¦  «         dS # t           j        $ r Y dS w xY w)a  Raise :class:`EntitiesForbidden` if ``data`` declares/refers an entity.

    Runs a standalone expat parse whose entity handlers raise on the first
    declaration or external reference.  ``data`` is fed to expat in its own type
    (``str`` or ``bytes``) so the pre-scan and the real ElementTree parse decode
    identically.  A malformed document raises ``ExpatError`` here; that is left
    for ElementTree to report so the error matches a direct parse, and it is not
    exploitable because the declaration would never be reached.
    c                 ó    — t          | ¦  «        ‚)Nr	   )r   Úrests     r   Ú_forbid_declarationz-_reject_entities.<locals>._forbid_declarationa   s   € Ý Ñ%Ô%Ð%r   c                  ó    — t          d¦  «        ‚)NÚexternalr	   )r   s    r   Ú_forbid_externalz*_reject_entities.<locals>._forbid_externald   s   € Ý 
Ñ+Ô+Ð+r   TN)r   ÚParserCreateÚEntityDeclHandlerÚExternalEntityRefHandlerÚParseÚ
ExpatError)ÚdataÚparserr   r    s       r   Ú_reject_entitiesr(   U   sˆ   € õ ÔÑ!Ô!€Fð&ð &ð &ð,ð ,ð ,ð  3€FÔØ&6€FÔ#ðØ�Š�T˜4Ñ Ô Ð Ð Ð øÝÔð ð ð ð 	ˆˆðøøøs   ©A ÁAÁAc                 ót   — t           rt          | ¦  «        S t          | ¦  «         t          j        | ¦  «        S )z<``ElementTree.fromstring`` that refuses entity declarations.)r   Ú_defused_fromstringr(   r   r   )Útexts    r   r   r   q   s7   € åð )Ý" 4Ñ(Ô(Ð(Ý�TÑÔÐÝÔ! $Ñ'Ô'Ð'r   c                 ó°  — t           rt          | ¦  «        S t          | d¦  «        r|                      ¦   «         }n<t	          | d¦  «        5 }|                     ¦   «         }ddd¦  «         n# 1 swxY w Y   t          |¦  «         t          |t          ¦  «        rt          j	        |¦  «        nt          j
        |¦  «        }t          j        |¦  «        S )a  ``ElementTree.parse`` that refuses entity declarations.

    ``source`` may be a filename or a file object.  In the fallback path a file
    object is read in full so it can be screened before parsing;
    ``ElementTree.parse`` reads it to the end regardless, so nothing is lost.
    ÚreadÚrbN)r   Ú_defused_parseÚhasattrr-   Úopenr(   Ú
isinstanceÚstrÚioÚStringIOÚBytesIOr   r   )Úsourcer&   ÚstreamÚbuffers       r   r   r   y   sø   € õ ð &Ý˜fÑ%Ô%Ð%åˆv�vÑÔð !Ø�{Š{‰}Œ}ˆˆå�&˜$ÑÔð 	! 6Ø—;’;‘=”=ˆDð	!ð 	!ð 	!ñ 	!ô 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!øøøð 	!ð 	!ð 	!ð 	!õ �TÑÔÐÝ",¨Tµ3Ñ"7Ô"7ÐM�RŒ[˜ÑÔÐ½R¼ZÈÑ=MÔ=M€FÝÔ˜VÑ$Ô$Ð$s   ÁA-Á-A1Á4A1)r   r4   Ú	xml.etreer   Úxml.parsersr   Ú__all__Ú
defusedxmlr   Údefusedxml.ElementTreer   r*   r   r/   r   ÚImportErrorÚ
ValueErrorr(   © r   r   ú<module>rB      s  ðð-ð -ð^ 
€	€	€	Ø !Ð !Ð !Ð !Ð !Ð !Ø Ð Ð Ð Ð Ð à
IÐ
IÐ
I€ðØ,Ð,Ð,Ð,Ð,Ð,ØHÐHÐHÐHÐHÐHØ>Ð>Ð>Ð>Ð>Ð>à€O€OøØð ð ð Ø€Oðð ð ð ð ˜Jñ ô ð ð ð ðøøøð(ð ð ð8(ð (ð (ð%ð %ð %ð %ð %s   ˜- ­AÁA