From 70ba3abd0c3c354e7e1214b70ab129c9e27b89a4 Mon Sep 17 00:00:00 2001 From: alperyoney Date: Thu, 5 Jun 2025 16:39:52 -0700 Subject: [PATCH 1/3] gh-116738: Inline append for local PyList --- Modules/grpmodule.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index 29da9936b65504..3fb5b1e666e9a6 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -7,6 +7,7 @@ #include "Python.h" #include "posixmodule.h" +#include "pycore_list.h" // _PyList_AppendTakeRef() #include // ERANGE #include // getgrgid_r() @@ -295,8 +296,12 @@ grp_getgrall_impl(PyObject *module) // setgrent()/endgrent() are not reentrant / thread-safe. A deadlock // is unlikely since mkgrent() should not be able to call arbitrary // Python code. + // `d` is a local list; append to it without a lock using + // _PyList_AppendTakeRef(). PyObject *v = mkgrent(module, p); - if (v == NULL || PyList_Append(d, v) != 0) { + if (v == NULL + || _PyList_AppendTakeRef((PyListObject *)d, Py_NewRef(v)) != 0) + { Py_XDECREF(v); Py_CLEAR(d); goto done; From d47b85cb96aab8b05918f94719d86c1a02350091 Mon Sep 17 00:00:00 2001 From: Alper Date: Tue, 10 Jun 2025 08:19:42 -0500 Subject: [PATCH 2/3] gh-116738: Assert list is uniquely referenced --- Modules/grpmodule.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index 3fb5b1e666e9a6..dde4aa85159b95 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -8,6 +8,7 @@ #include "Python.h" #include "posixmodule.h" #include "pycore_list.h" // _PyList_AppendTakeRef() +#include "pycore_object.h" // _PyObject_IsUniquelyReferenced() #include // ERANGE #include // getgrgid_r() @@ -291,13 +292,14 @@ grp_getgrall_impl(PyObject *module) setgrent(); struct group *p; + // `d` is a local list; append items without a lock using + // _PyList_AppendTakeRef() within the loop. + assert(_PyObject_IsUniquelyReferenced(d)); while ((p = getgrent()) != NULL) { // gh-126316: Don't release the mutex around mkgrent() since // setgrent()/endgrent() are not reentrant / thread-safe. A deadlock // is unlikely since mkgrent() should not be able to call arbitrary // Python code. - // `d` is a local list; append to it without a lock using - // _PyList_AppendTakeRef(). PyObject *v = mkgrent(module, p); if (v == NULL || _PyList_AppendTakeRef((PyListObject *)d, Py_NewRef(v)) != 0) From cf5d8ec8a604b40fab080697e0c6fb84c3f48de9 Mon Sep 17 00:00:00 2001 From: alperyoney Date: Tue, 10 Jun 2025 14:48:29 -0700 Subject: [PATCH 3/3] gh-116738: Let _PyList_AppendTakeRef() steal the reference --- Modules/grpmodule.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index dde4aa85159b95..e71f4ea8cb6b45 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -301,14 +301,10 @@ grp_getgrall_impl(PyObject *module) // is unlikely since mkgrent() should not be able to call arbitrary // Python code. PyObject *v = mkgrent(module, p); - if (v == NULL - || _PyList_AppendTakeRef((PyListObject *)d, Py_NewRef(v)) != 0) - { - Py_XDECREF(v); + if (v == NULL || _PyList_AppendTakeRef((PyListObject *)d, v) != 0) { Py_CLEAR(d); goto done; } - Py_DECREF(v); } done: