From a59525cc69bc2bc2f0c40e4bf86674aa5906eeef Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 20 Nov 2019 09:26:29 -0800 Subject: [PATCH 1/8] Add private _PyModule_StealObject API. --- Python/modsupport.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Python/modsupport.c b/Python/modsupport.c index 62558221077468..a3a9eca772021b 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -655,6 +655,19 @@ PyModule_AddObject(PyObject *m, const char *name, PyObject *o) return 0; } +/* Like PyModule_AddObject, but steals o on success AND failure. + This is probably what you want! */ + +int +_PyModule_StealObject(PyObject *m, const char *name, PyObject *o) +{ + if (PyModule_AddObject(m, name, o) < 0) { + Py_XDECREF(o); + return -1; + } + return 0; +} + int PyModule_AddIntConstant(PyObject *m, const char *name, long value) { From f3e806e15e2d5f4e494afac9b2d366f476cf49a6 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 20 Nov 2019 10:39:21 -0800 Subject: [PATCH 2/8] Add _PyModule_StealObject to modsupport.h. --- Include/modsupport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Include/modsupport.h b/Include/modsupport.h index f90ede4831e32b..2052725eec2558 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -134,6 +134,7 @@ void _PyArg_Fini(void); #endif /* Py_LIMITED_API */ PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *); +PyAPI_FUNC(int) _PyModule_StealObject(PyObject *, const char *, PyObject *); PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long); PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *); #define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c) From 440bb722cedd11d32393024c24a510b9b12d632e Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2019 18:47:51 +0000 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/C API/2019-11-20-18-47-48.bpo-38823.x1nghH.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/C API/2019-11-20-18-47-48.bpo-38823.x1nghH.rst diff --git a/Misc/NEWS.d/next/C API/2019-11-20-18-47-48.bpo-38823.x1nghH.rst b/Misc/NEWS.d/next/C API/2019-11-20-18-47-48.bpo-38823.x1nghH.rst new file mode 100644 index 00000000000000..82d0b07cc13997 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-11-20-18-47-48.bpo-38823.x1nghH.rst @@ -0,0 +1,3 @@ +Add a new private ``_PyModule_StealObject`` API. It is identical to :c:func:`PyModule_AddObject`, but steals a reference to the added object on both success *and* failure. + +Patch by Brandt Bucher. \ No newline at end of file From 418d79bdcdcb3e59adcb5737f7bbf859b59c0bcb Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 27 Jan 2020 17:26:09 -0800 Subject: [PATCH 4/8] Clean up refleaks in _warnings initialization. --- Python/_warnings.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/_warnings.c b/Python/_warnings.c index b8585d204787db..0ec7452d0e9d10 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1353,17 +1353,17 @@ _PyWarnings_Init(void) } Py_INCREF(st->filters); - if (PyModule_AddObject(m, "filters", st->filters) < 0) { + if (_PyModule_StealObject(m, "filters", st->filters) < 0) { goto error; } Py_INCREF(st->once_registry); - if (PyModule_AddObject(m, "_onceregistry", st->once_registry) < 0) { + if (_PyModule_StealObject(m, "_onceregistry", st->once_registry) < 0) { goto error; } Py_INCREF(st->default_action); - if (PyModule_AddObject(m, "_defaultaction", st->default_action) < 0) { + if (_PyModule_StealObject(m, "_defaultaction", st->default_action) < 0) { goto error; } From 5fef8fb71ec68850f972531b16bab06c5e39033d Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 27 Jan 2020 17:26:36 -0800 Subject: [PATCH 5/8] Clean up refleaks in _msi initialization. --- PC/_msi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PC/_msi.c b/PC/_msi.c index accbe7a7206944..ddd2b26831d82b 100644 --- a/PC/_msi.c +++ b/PC/_msi.c @@ -1120,6 +1120,9 @@ PyInit__msi(void) MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL); if (!MSIError) return NULL; - PyModule_AddObject(m, "MSIError", MSIError); + if (_PyModule_StealObject(m, "MSIError", MSIError) < 0) { + Py_DECREF(m); + return NULL; + } return m; } From b1fb2760a527c3db3418a7c6d54d4f21cf8c8eba Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 27 Jan 2020 17:26:46 -0800 Subject: [PATCH 6/8] Clean up refleaks in _functools initialization. --- Modules/_functoolsmodule.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 987087b1ac97ba..6e8b7c0f69a234 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1457,7 +1457,10 @@ PyInit__functools(void) } name = _PyType_Name(typelist[i]); Py_INCREF(typelist[i]); - PyModule_AddObject(m, name, (PyObject *)typelist[i]); + if (_PyModule_StealObject(m, name, (PyObject *)typelist[i]) < 0) { + Py_DECREF(m); + return NULL; + } } return m; } From 08a80609bc3d72fc9a832df2543933bfb47bf30c Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 27 Jan 2020 17:26:57 -0800 Subject: [PATCH 7/8] Clean up refleaks in _collections initialization. --- Modules/_collectionsmodule.c | 53 +++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 1d23973fd05661..1b3c053bc4d605 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2539,34 +2539,55 @@ PyInit__collections(void) if (m == NULL) return NULL; - if (PyType_Ready(&deque_type) < 0) - return NULL; + if (PyType_Ready(&deque_type) < 0) { + goto fail; + } Py_INCREF(&deque_type); - PyModule_AddObject(m, "deque", (PyObject *)&deque_type); + if (_PyModule_StealObject(m, "deque", (PyObject *)&deque_type) < 0) { + goto fail; + } defdict_type.tp_base = &PyDict_Type; - if (PyType_Ready(&defdict_type) < 0) - return NULL; + if (PyType_Ready(&defdict_type) < 0) { + goto fail; + } Py_INCREF(&defdict_type); - PyModule_AddObject(m, "defaultdict", (PyObject *)&defdict_type); + if (_PyModule_StealObject(m, "defaultdict", (PyObject *)&defdict_type) < 0) { + goto fail; + } Py_INCREF(&PyODict_Type); - PyModule_AddObject(m, "OrderedDict", (PyObject *)&PyODict_Type); + if (_PyModule_StealObject(m, "OrderedDict", (PyObject *)&PyODict_Type) < 0) { + goto fail; + } - if (PyType_Ready(&dequeiter_type) < 0) - return NULL; + if (PyType_Ready(&dequeiter_type) < 0) { + goto fail; + } Py_INCREF(&dequeiter_type); - PyModule_AddObject(m, "_deque_iterator", (PyObject *)&dequeiter_type); + if (_PyModule_StealObject(m, "_deque_iterator", (PyObject *)&dequeiter_type) < 0) { + goto fail; + } - if (PyType_Ready(&dequereviter_type) < 0) - return NULL; + if (PyType_Ready(&dequereviter_type) < 0) { + goto fail; + } Py_INCREF(&dequereviter_type); - PyModule_AddObject(m, "_deque_reverse_iterator", (PyObject *)&dequereviter_type); + if (_PyModule_StealObject(m, "_deque_reverse_iterator", (PyObject *)&dequereviter_type) < 0) { + goto fail; + } - if (PyType_Ready(&tuplegetter_type) < 0) - return NULL; + if (PyType_Ready(&tuplegetter_type) < 0) { + goto fail; + } Py_INCREF(&tuplegetter_type); - PyModule_AddObject(m, "_tuplegetter", (PyObject *)&tuplegetter_type); + if (_PyModule_StealObject(m, "_tuplegetter", (PyObject *)&tuplegetter_type) < 0) { + goto fail; + } return m; + +fail: + Py_DECREF(m); + return NULL; } From 95f9800880007ff0fbd5b52834c6b6a9c678a42f Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 27 Jan 2020 17:27:12 -0800 Subject: [PATCH 8/8] Clean up refleaks in _bz2 initialization. --- Modules/_bz2module.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index 31bbf66104119c..afc0614b4119d3 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -755,11 +755,20 @@ PyInit__bz2(void) return NULL; Py_INCREF(&BZ2Compressor_Type); - PyModule_AddObject(m, "BZ2Compressor", (PyObject *)&BZ2Compressor_Type); + if (_PyModule_StealObject(m, "BZ2Compressor", + (PyObject *)&BZ2Compressor_Type) < 0) { + goto fail; + } Py_INCREF(&BZ2Decompressor_Type); - PyModule_AddObject(m, "BZ2Decompressor", - (PyObject *)&BZ2Decompressor_Type); + if (_PyModule_StealObject(m, "BZ2Decompressor", + (PyObject *)&BZ2Decompressor_Type) < 0) { + goto fail; + } return m; + +fail: + Py_DECREF(m); + return NULL; }