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 — NULL deref + Double Py_DECREF in pyexpat ExternalEntityParserCreate() · Issue #144984 · python/cpython

NULL deref + Double Py_DECREF in pyexpat ExternalEntityParserCreate() #144984

New issue
Copy link
New issue
Copy link
Closed
Closed
NULL deref + Double Py_DECREF in pyexpat ExternalEntityParserCreate()#144984
Copy link
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-XMLtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@raminfp
raminfp
opened on Feb 19, 2026
Issue body actions

Bug report

Bug description:

When ExternalEntityParserCreate() hits an error path (allocation failure), Py_DECREF(new_parser) is called on a partially-initialized object. This has two problems:

  1. new_parser->handlers is NULL (set to 0 at line 1094), so xmlparse_dealloc to clear_handlers dereferences NULL to SEGV
  2. new_parser->parent holds a strong ref to self, so Py_DECREF(new_parser) already decrements self via Py_CLEAR(parent) in dealloc. The explicit Py_DECREF(self) on the next line is a double decrement.

All three error paths in the function have the same issue (lines 1100-1101, 1106-1107, 1120-1121).

Modules/pyexpat.c, pyexpat_xmlparser_ExternalEntityParserCreate_impl():

Py_INCREF(self);                                    // line 1082

new_parser->parent = (PyObject *)self;              // line 1093
new_parser->handlers = 0;                           // line 1094 - NULL

// error path (e.g. buffer malloc failure):
if (new_parser->buffer == NULL) {
    Py_DECREF(new_parser);                          // line 1100 => dealloc
                                                    //   clear_handlers(NULL) => SEGV
                                                    //   Py_CLEAR(parent) => Py_DECREF(self) [1st]
    Py_DECREF(self);                                // line 1101 [2nd, over-decrement]
    return PyErr_NoMemory();
}

Uses _testcapi.set_nomemory() to force an allocation failure inside ExternalEntityParserCreate():

import xml.parsers.expat
import _testcapi

parser = xml.parsers.expat.ParserCreate()
parser.buffer_text = True

_testcapi.set_nomemory(1, 10)
sub = parser.ExternalEntityParserCreate(None)

With an ASAN build (./configure --with-address-sanitizer --with-pydebug):

./python pyexpat.py

AddressSanitizer:DEADLYSIGNAL
=================================================================
==43632==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7d907b981b73 bp 0x7ffecf69fa50 sp 0x7ffecf69fa30 T0)
==43632==The signal is caused by a READ memory access.
==43632==Hint: address points to the zero page.
    #0 0x7d907b981b73 in clear_handlers Modules/pyexpat.c:2497
    #1 0x7d907b981c2c in xmlparse_clear Modules/pyexpat.c:1548
    #2 0x7d907b989554 in xmlparse_dealloc Modules/pyexpat.c:1562
    #3 0x5c347de9f287 in _Py_Dealloc Objects/object.c:3271
    #4 0x7d907b981994 in Py_DECREF Include/refcount.h:403
    #5 0x7d907b9878fd in pyexpat_xmlparser_ExternalEntityParserCreate_impl Modules/pyexpat.c:1106
    #6 0x7d907b987fe5 in pyexpat_xmlparser_ExternalEntityParserCreate Modules/clinic/pyexpat.c.h:313
    #7 0x5c347ddfb9f2 in method_vectorcall_FASTCALL_KEYWORDS_METHOD Objects/descrobject.c:381
    #8 0x5c347dddbd0c in _PyObject_VectorcallTstate Include/internal/pycore_call.h:136
    #9 0x5c347dddbdff in PyObject_Vectorcall Objects/call.c:327
    #10 0x5c347e059777 in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:769
    #11 0x5c347e069714 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1817
    #12 0x5c347e0a0961 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:118
    #13 0x5c347e0a0cc7 in _PyEval_Vector Python/ceval.c:2132
    #14 0x5c347e0a0f7d in PyEval_EvalCode Python/ceval.c:680
    #15 0x5c347e1a4631 in run_eval_code_obj Python/pythonrun.c:1366
    #16 0x5c347e1a4977 in run_mod Python/pythonrun.c:1469
    #17 0x5c347e1a58ac in pyrun_file Python/pythonrun.c:1294
    #18 0x5c347e1a86e2 in _PyRun_SimpleFileObject Python/pythonrun.c:518
    #19 0x5c347e1a898e in _PyRun_AnyFileObject Python/pythonrun.c:81
    #20 0x5c347e1fd936 in pymain_run_file_obj Modules/main.c:410
    #21 0x5c347e1fdba3 in pymain_run_file Modules/main.c:429
    #22 0x5c347e1ff3a1 in pymain_run_python Modules/main.c:691
    #23 0x5c347e1ffa37 in Py_RunMain Modules/main.c:772
    #24 0x5c347e1ffc23 in pymain_main Modules/main.c:802
    #25 0x5c347e1fffa8 in Py_BytesMain Modules/main.c:826
    #26 0x5c347dc66675 in main Programs/python.c:15
    #27 0x7d907c42a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #28 0x7d907c42a47a in __libc_start_main_impl ../csu/libc-start.c:360
    #29 0x5c347dc665a4 in _start (/home/raminfp/Projects/cpython/python+0x2ed5a4) (BuildId: a8bec32f918132a019758b07f370e97d9e763c6f)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV Modules/pyexpat.c:2497 in clear_handlers
==43632==ABORTING

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

  • gh-144984: Fix crash in ExternalEntityParserCreate() error paths #144992
  • [3.14] gh-144984: Fix crash in Expat's ExternalEntityParserCreate error paths (GH-144992) #146019
  • [3.13] gh-144984: Fix crash in Expat's ExternalEntityParserCreate error paths (GH-144992) #146142
  • gh-144984: Skip test under tracerefs #146218
  • [3.14] gh-144984: Skip test under tracerefs (GH-146218) #146384

Activity

  1. raminfp
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Feb 19, 2026
  2. raminfp commented on Feb 19, 2026

    @raminfp
    raminfp
    on Feb 19, 2026
    ContributorAuthor
    More actions

    The bug was introduced with the parent field (gh-139400 fix).

  3. StanFromIreland
    added
    extension-modulesC modules in the Modules dirC modules in the Modules dir
    topic-XML
    on Feb 19, 2026
  4. picnixz
    marked Double Py_DECREF on parent parser in pyexpat.xmlparser.ExternalEntityParserCreate error paths #145989 as a duplicate of this issue on Mar 16, 2026
  5. picnixz
    added a commit that references this issue on Mar 16, 2026

    gh-144984: Fix crash in Expat's `ExternalEntityParserCreate` error pa…

    e6b9a14
  6. miss-islington
    added a commit that references this issue on Mar 16, 2026

    pythongh-144984: Fix crash in Expat's `ExternalEntityParserCreate` er…

    6da136f
  7. picnixz
    added a commit that references this issue on Mar 17, 2026

    [3.14] gh-144984: Fix crash in Expat's `ExternalEntityParserCreate` e…

    0548f41
  8. devdanzin
    marked NULL dereference in pyexpat clear_handlers #146079 as a duplicate of this issue on Mar 17, 2026
  9. encukou
    added 2 commits that reference this issue on Mar 20, 2026

    pythongh-144984: Skip test unper tracerefs

    88dc467

    pythongh-144984: Skip test under tracerefs

    46d92b7
  10. encukou commented on Mar 20, 2026

    @encukou
    encukou
    on Mar 20, 2026
    Member
    More actions

    The test added in GH-144992 fails in tracerefs mode, which needs memory allocation for its validation magic, and fails after testcapi.set_nomemory.
    Example failure: https://buildbot.python.org/#/builders/1747/builds/263/steps/6/logs/stdio

    I'll send a PR.

    Reacted by Ramin Farajpour Cami
  11. encukou
    added a commit that references this issue on Mar 24, 2026

    gh-144984: Skip test under tracerefs (GH-146218)

    119fce7
  12. miss-islington
    added a commit that references this issue on Mar 24, 2026

    pythongh-144984: Skip test under tracerefs (pythonGH-146218)

    907e4c3
  13. encukou
    added a commit that references this issue on Mar 25, 2026

    [3.14] gh-144984: Skip test under tracerefs (GH-146218) (GH-146384)

    4f5f6ea
  14. Yhg1s
    added a commit that references this issue on Apr 7, 2026

    [3.13] gh-144984: Fix crash in Expat's `ExternalEntityParserCreate` e…

    4c8d6f4
  15. gpshead commented on Apr 11, 2026

    @gpshead
    gpshead
    on Apr 11, 2026
    Member
    More actions

    thanks, this appears to be fixed now!

  16. gpshead
    closed this as completedon Apr 11, 2026
  17. clin1234
    added a commit that references this issue on Apr 16, 2026

    pythongh-144984: Skip test under tracerefs (pythonGH-146218)

    9698501
  18. ljfp
    added 2 commits that reference this issue on Apr 25, 2026

    pythongh-144984: Fix crash in Expat's `ExternalEntityParserCreate` er…

    585ade9

    pythongh-144984: Skip test under tracerefs (pythonGH-146218)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-XMLtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402520 — 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.