REDHAT-BUG-2529697: Use After Free

Published Sep 8, 2026
·
Updated

SUMMARY A double-free / use-after-free exists in the SAX attributeDecl callback handler (pythonAttributeDecl in python/libxml.c). When parsing XML containing a DTD <!ATTLIST> declaration with enumerated attribute values, each value string is freed twice: PyListSetItem() steals the reference, and an explicit PyDECREF() then drops the refcount to zero and frees the object, leaving a dangling pointer in the list.

AFFECTED COMPONENT

libxml2 with Python bindings enabled (python3-libxml2 / libxml2-python)

The defect is long-standing; the affected code in pythonAttributeDecl has been unchanged for many years.

Reproduced on upstream commit 4b35628e97472eaf23d8a841d2f711f7c2f96255 (2026-02-24).

IMPACT

Denial of service: 100% reproducible crash (SIGSEGV) in any Python application that uses the libxml2 SAX bindings (libxml2.createPushParser), registers an attributeDecl handler, and parses untrusted XML with a DTD <!ATTLIST> containing enumerated values. Verified 10/10 in isolated processes.

The use-after-free is also potentially exploitable for code execution: I was able to demonstrate hijacking the freed object's tpdealloc function pointer in-process. Full remote code execution would require additional heap grooming and is not demonstrated. I'd defer to your team on final severity scoring; I'd characterize the reliably demonstrated impact as DoS, with code execution as a credible but conditional escalation.

ROOT CAUSE (python/libxml.c, pythonAttributeDecl)

for (node = tree; node != NULL; node = node->next) { newName = PYIMPORTSTRING((char ) node->name); PyListSetItem(nameList, count, newName); / steals reference / PyDECREF(newName); / double-free / count++; }

PyListSetItem() does not increment the refcount, so the subsequent PyDECREF() over-decrements. Because of CPython pymalloc free-list reuse, list entries can end up pointing at the same freed address; cleanup after the SAX callback then decrefs dangling pointers and corrupts allocator state.

PROOF OF CONCEPT (minimal DoS)

import libxml2 class Handler: def attributeDecl(self, args): pass def startElement(self, a): pass def endElement(self, a): pass def characters(self, a): pass xml = b'''<?xml version="1.0"?> <!DOCTYPE r [ <!ELEMENT r EMPTY> <!ATTLIST r a (xx|yy|zz|ww|qq) "xx"> ]> <r a="xx"/>''' h = Handler() c = libxml2.createPushParser(h, "", 0, "t") c.parseChunk(xml, len(xml), 1) # SIGSEGV

UPSTREAM FIX (already merged and closed)

Fix: remove the erroneous PyDECREF(newName) since PyListSetItem already takes ownership.

Merge request: https://gitlab.gnome.org/GNOME/libxml2/-/mergerequests/397 ("python: Do not decref string after adding to the list")

Fix commit: 046931e6

Issue report: https://gitlab.gnome.org/GNOME/libxml2/-/workitems/1076

Upstream maintainer Nick Wellnhofer confirmed it appears to be a security issue and asked that a CVE be requested; the maintainer who merged the fix indicated CVE assignment is not handled by the project itself.

SUGGESTED CLASSIFICATION

CWE-415 (Double Free), leading to CWE-416 (Use After Free)

ENVIRONMENT

OS: Ubuntu 22.04 x8664; Python 3.10.12; GCC 11.4.0; libxml2 built from source with -fsanitize=address.

I'm happy to provide the full ASan trace or the code-execution PoC on request. Please let me know if you need anything else to proceed.

Thank you, Adnan Jakati!https://mailtrack.io/trace/mail/773e02eeb348f92b41f2a5d93b4c46af0007ab1f.png?u=12519192!

Affected Software

3 affected components
Gnome libxml2
python3-libxml2
libxml2-python

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade libxml2-python (libxml2 createPushParser / SAX bindings, python/libxml.c pythonAttributeDecl) to a version that resolves this vulnerability.

    Patch 046931e6

Event History

Sep 8, 2026
Data Sourced
via Red Hat·07:30 AM
DescriptionSeverityAffected Software

Frequently Asked Questions

1

Which deployments should be prioritized for triage?

Prioritize Python applications using the libxml2 SAX bindings through libxml2.createPushParser, particularly where python3-libxml2 or libxml2-python is installed and the application processes untrusted XML.

2

What input and application behavior are required to trigger the crash?

The application must register an attributeDecl handler and parse XML containing a DTD <!ATTLIST> declaration with enumerated attribute values. Under those conditions, the issue was reported as a 100% reproducible SIGSEGV in isolated-process testing.

3

Is the impact limited to denial of service?

A denial of service crash is confirmed. The report also describes an in-process demonstration of hijacking the freed object's tp_dealloc function pointer, so code execution is considered potentially possible, but full remote code execution is not confirmed in the provided data.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203