Bug 2529705
| Summary: | CVE-2026-74860 pcem: double-free/UAF in libxml2 Python bindings [fedora-all] | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Dhananjay Arunesh <darunesh> |
| Component: | pcem | Assignee: | Davide Cavalca <davide> |
| Status: | NEW --- | QA Contact: | |
| Severity: | high | Docs Contact: | |
| Priority: | high | ||
| Version: | rawhide | CC: | davide |
| Target Milestone: | --- | Keywords: | Security, SecurityTracking |
| Target Release: | --- | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| Whiteboard: | {"flaws": ["640e450a-09f3-4de3-8000-31f181351f28"]} | ||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | --- | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | |||
| Bug Blocks: | 2529697 | ||
Disclaimer: Community trackers are created by Red Hat Product Security team on a best effort basis. Package maintainers are required to ascertain if the flaw indeed affects their package, before starting the update process. 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: PyList_SetItem() steals the reference, and an explicit Py_DECREF() 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 tp_dealloc 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 = PY_IMPORT_STRING((char *) node->name); PyList_SetItem(nameList, count, newName); /* steals reference */ Py_DECREF(newName); /* double-free */ count++; } PyList_SetItem() does not increment the refcount, so the subsequent Py_DECREF() 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 Py_DECREF(newName) since PyList_SetItem already takes ownership. Merge request: https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/397 ("python: Do not decref string after adding to the list") Fix commit: 046931e6 Issue report: https://gitlab.gnome.org/GNOME/libxml2/-/work_items/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 x86_64; 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!