"""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())