GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — `xml.dom.minidom.parseString()` takes quadratic time on text delivered in many pieces · Issue #160525 · python/cpython

xml.dom.minidom.parseString() takes quadratic time on text delivered in many pieces #160525

New issue
Copy link
New issue
Copy link
Open
#160526
Open
xml.dom.minidom.parseString() takes quadratic time on text delivered in many pieces#160525
#160526
Copy link
Assignees
gpshead
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-XMLtype-securityA security issueA security issue

Description

@gpshead
gpshead
opened on Oct 23, 2026
Issue body actions

Bug report

Bug description:

xml.dom.minidom.parse() and parseString() take time quadratic in the number of pieces in which Expat delivers a run of character data. xml.dom.expatbuilder extends the current Text node with node.data = node.data + data on every CharacterDataHandler call, and pyexpat flushes its text buffer before every other handler, so markup that adds no node (an empty CDATA section, a reference to an external entity) splits one text node into many callbacks. With the pieces placed in an internal entity that is referenced repeatedly, a few kilobytes of input are enough.

Whoever supplies the document controls this; a program that parses XML from an untrusted source with minidom's default arguments can be made to spend about a minute of CPU on a 7 kB document.

import time
from xml.dom import minidom

def make(k):
    return ('<!DOCTYPE r [<!ENTITY x "%s">]><r>%s</r>'
            % ('ab<![CDATA[]]>' * k, '&x;' * k))

for k in 100, 200, 400:
    doc = make(k)
    t = time.process_time()
    dom = minidom.parseString(doc)
    t = time.process_time() - t
    print(f'{len(doc)} bytes -> {len(dom.documentElement.firstChild.data)} chars of text, {t:.2f} s')

Output on a debug build of main:

1736 bytes -> 20000 chars of text, 0.44 s
3436 bytes -> 80000 chars of text, 3.25 s
6836 bytes -> 320000 chars of text, 68.81 s

The time should grow with the amount of text (4x per step here), not with its square. The code is unchanged since Python 2.3. gh-158860 is the same pattern in Node.normalize(); gh-142145 was a similar issue elsewhere in minidom.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

  • gh-160525: Fix quadratic text concatenation in xml.dom.expatbuilder #160526

Activity

  1. gpshead
    self-assigned this
    on Oct 23, 2026
  2. gpshead
    added
    type-securityA security issueA security issue
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    topic-XML
    on Oct 23, 2026
  3. gpshead
    added a commit that references this issue on Oct 23, 2026

    pythongh-160525: Keep expatbuilder text correct when handlers are ove…

    99347be
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @gpshead
    gpshead

Labels

stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-XMLtype-securityA security issueA security issue

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.