|
1 | 1 | /* UNIX group file access module */ |
2 | 2 |
|
3 | | -// Need limited C API version 3.13 for PyMem_RawRealloc() |
4 | | -#include "pyconfig.h" // Py_GIL_DISABLED |
5 | | -#ifndef Py_GIL_DISABLED |
6 | | -#define Py_LIMITED_API 0x030d0000 |
| 3 | +// Argument Clinic uses the internal C API |
| 4 | +#ifndef Py_BUILD_CORE_BUILTIN |
| 5 | +# define Py_BUILD_CORE_MODULE 1 |
7 | 6 | #endif |
8 | 7 |
|
9 | 8 | #include "Python.h" |
@@ -110,20 +109,15 @@ mkgrent(PyObject *module, struct group *p) |
110 | 109 | return v; |
111 | 110 | } |
112 | 111 |
|
113 | | -/*[clinic input] |
114 | | -grp.getgrgid |
115 | | -
|
116 | | - id: object |
117 | | -
|
118 | | -Return the group database entry for the given numeric group ID. |
119 | | -
|
120 | | -If id is not valid, raise KeyError. |
121 | | -[clinic start generated code]*/ |
122 | | - |
123 | 112 | static PyObject * |
124 | | -grp_getgrgid_impl(PyObject *module, PyObject *id) |
125 | | -/*[clinic end generated code: output=30797c289504a1ba input=15fa0e2ccf5cda25]*/ |
| 113 | +grp_getgrgid(PyObject *module, PyObject *args, PyObject *kwargs) |
126 | 114 | { |
| 115 | + static char *kwlist[] = {"id", NULL}; |
| 116 | + PyObject *id; |
| 117 | + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &id)) { |
| 118 | + return NULL; |
| 119 | + } |
| 120 | + |
127 | 121 | PyObject *retval = NULL; |
128 | 122 | int nomem = 0; |
129 | 123 | char *buf = NULL, *buf2 = NULL; |
@@ -190,6 +184,15 @@ grp_getgrgid_impl(PyObject *module, PyObject *id) |
190 | 184 | return retval; |
191 | 185 | } |
192 | 186 |
|
| 187 | +PyDoc_STRVAR(grp_getgrgid__doc__, |
| 188 | +"getgrgid($module, /, id)\n" |
| 189 | +"--\n" |
| 190 | +"\n" |
| 191 | +"Return the group database entry for the given numeric group ID.\n" |
| 192 | +"\n" |
| 193 | +"If id is not valid, raise KeyError."); |
| 194 | + |
| 195 | + |
193 | 196 | /*[clinic input] |
194 | 197 | grp.getgrnam |
195 | 198 |
|
@@ -281,28 +284,38 @@ static PyObject * |
281 | 284 | grp_getgrall_impl(PyObject *module) |
282 | 285 | /*[clinic end generated code: output=585dad35e2e763d7 input=d7df76c825c367df]*/ |
283 | 286 | { |
284 | | - PyObject *d; |
285 | | - struct group *p; |
286 | | - |
287 | | - if ((d = PyList_New(0)) == NULL) |
| 287 | + PyObject *d = PyList_New(0); |
| 288 | + if (d == NULL) { |
288 | 289 | return NULL; |
| 290 | + } |
| 291 | + |
| 292 | + static PyMutex getgrall_mutex = {0}; |
| 293 | + PyMutex_Lock(&getgrall_mutex); |
289 | 294 | setgrent(); |
| 295 | + |
| 296 | + struct group *p; |
290 | 297 | while ((p = getgrent()) != NULL) { |
| 298 | + // gh-126316: Don't release the mutex around mkgrent() since |
| 299 | + // setgrent()/endgrent() are not reentrant / thread-safe. A deadlock |
| 300 | + // is unlikely since mkgrent() should not be able to call arbitrary |
| 301 | + // Python code. |
291 | 302 | PyObject *v = mkgrent(module, p); |
292 | 303 | if (v == NULL || PyList_Append(d, v) != 0) { |
293 | 304 | Py_XDECREF(v); |
294 | | - Py_DECREF(d); |
295 | | - endgrent(); |
296 | | - return NULL; |
| 305 | + Py_CLEAR(d); |
| 306 | + goto done; |
297 | 307 | } |
298 | 308 | Py_DECREF(v); |
299 | 309 | } |
| 310 | + |
| 311 | +done: |
300 | 312 | endgrent(); |
| 313 | + PyMutex_Unlock(&getgrall_mutex); |
301 | 314 | return d; |
302 | 315 | } |
303 | 316 |
|
304 | 317 | static PyMethodDef grp_methods[] = { |
305 | | - GRP_GETGRGID_METHODDEF |
| 318 | + {"getgrgid", _PyCFunction_CAST(grp_getgrgid), METH_VARARGS|METH_KEYWORDS, grp_getgrgid__doc__}, |
306 | 319 | GRP_GETGRNAM_METHODDEF |
307 | 320 | GRP_GETGRALL_METHODDEF |
308 | 321 | {NULL, NULL} |
|
0 commit comments