"""Import upload guards: decompression-bomb docx must be rejected before parsing (H2 DoS)."""
from __future__ import annotations
import io
import zipfile
import pytest
from docx import Document
from app.document_extractors import ImportExtractionError, extract_text
CT = (''
''
''
'')
RELS = (''
'')
def _custom_docx(document_xml: str) -> bytes:
buffer = io.BytesIO()
with zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr("[Content_Types].xml", CT)
zf.writestr("_rels/.rels", RELS)
zf.writestr("word/document.xml", document_xml)
return buffer.getvalue()
def test_decompression_bomb_docx_is_rejected_before_parsing() -> None:
"""~20MB decompressed XML must fail fast instead of burning CPU in the parser."""
para = "放大攻击"
body = para * (20 * 1024 * 1024 // len(para.encode()))
bomb = _custom_docx(''
''
f"{body}")
assert len(bomb) < 1024 * 1024 # small compressed payload is the point of the attack
with pytest.raises(ImportExtractionError):
extract_text(extension=".docx", content=bomb)
def test_normal_docx_still_parses() -> None:
document = Document()
document.add_paragraph("张三 后端工程师")
buffer = io.BytesIO()
document.save(buffer)
assert "张三" in extract_text(extension=".docx", content=buffer.getvalue())