|
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