@@ -50,6 +50,8 @@ exception is raised if the entry asked for cannot be found.");
5050static int initialized ;
5151static PyTypeObject StructPwdType ;
5252
53+ #define DEFAULT_BUFFER_SIZE 1024
54+
5355static void
5456sets (PyObject * v , int i , const char * val )
5557{
@@ -116,16 +118,59 @@ static PyObject *
116118pwd_getpwuid (PyObject * module , PyObject * uidobj )
117119/*[clinic end generated code: output=c4ee1d4d429b86c4 input=ae64d507a1c6d3e8]*/
118120{
121+ PyObject * retval = NULL ;
119122 uid_t uid ;
123+ int nomem = 0 ;
120124 struct passwd * p ;
125+ char * buf = NULL , * buf2 = NULL ;
121126
122127 if (!_Py_Uid_Converter (uidobj , & uid )) {
123128 if (PyErr_ExceptionMatches (PyExc_OverflowError ))
124129 PyErr_Format (PyExc_KeyError ,
125130 "getpwuid(): uid not found" );
126131 return NULL ;
127132 }
128- if ((p = getpwuid (uid )) == NULL ) {
133+ #ifdef HAVE_GETPWUID_R
134+ Py_BEGIN_ALLOW_THREADS
135+ int status ;
136+ Py_ssize_t bufsize ;
137+ struct passwd pwd ;
138+
139+ bufsize = sysconf (_SC_GETPW_R_SIZE_MAX );
140+ if (bufsize == -1 ) {
141+ bufsize = DEFAULT_BUFFER_SIZE ;
142+ }
143+
144+ while (1 ) {
145+ buf2 = PyMem_RawRealloc (buf , bufsize );
146+ if (buf2 == NULL ) {
147+ nomem = 1 ;
148+ break ;
149+ }
150+ buf = buf2 ;
151+ status = getpwuid_r (uid , & pwd , buf , bufsize , & p );
152+ if (status != 0 ) {
153+ p = NULL ;
154+ }
155+ if (p != NULL || status != ERANGE ) {
156+ break ;
157+ }
158+ if (bufsize > (PY_SSIZE_T_MAX >> 1 )) {
159+ nomem = 1 ;
160+ break ;
161+ }
162+ bufsize <<= 1 ;
163+ }
164+
165+ Py_END_ALLOW_THREADS
166+ #else
167+ p = getpwuid (uid );
168+ #endif
169+ if (p == NULL ) {
170+ PyMem_RawFree (buf );
171+ if (nomem == 1 ) {
172+ return PyErr_NoMemory ();
173+ }
129174 PyObject * uid_obj = _PyLong_FromUid (uid );
130175 if (uid_obj == NULL )
131176 return NULL ;
@@ -134,7 +179,11 @@ pwd_getpwuid(PyObject *module, PyObject *uidobj)
134179 Py_DECREF (uid_obj );
135180 return NULL ;
136181 }
137- return mkpwent (p );
182+ retval = mkpwent (p );
183+ #ifdef HAVE_GETPWUID_R
184+ PyMem_RawFree (buf );
185+ #endif
186+ return retval ;
138187}
139188
140189/*[clinic input]
@@ -152,7 +201,8 @@ static PyObject *
152201pwd_getpwnam_impl (PyObject * module , PyObject * arg )
153202/*[clinic end generated code: output=6abeee92430e43d2 input=d5f7e700919b02d3]*/
154203{
155- char * name ;
204+ char * buf = NULL , * buf2 = NULL , * name ;
205+ int nomem = 0 ;
156206 struct passwd * p ;
157207 PyObject * bytes , * retval = NULL ;
158208
@@ -161,13 +211,55 @@ pwd_getpwnam_impl(PyObject *module, PyObject *arg)
161211 /* check for embedded null bytes */
162212 if (PyBytes_AsStringAndSize (bytes , & name , NULL ) == -1 )
163213 goto out ;
164- if ((p = getpwnam (name )) == NULL ) {
165- PyErr_Format (PyExc_KeyError ,
166- "getpwnam(): name not found: %s" , name );
214+ #ifdef HAVE_GETPWNAM_R
215+ Py_BEGIN_ALLOW_THREADS
216+ int status ;
217+ Py_ssize_t bufsize ;
218+ struct passwd pwd ;
219+
220+ bufsize = sysconf (_SC_GETPW_R_SIZE_MAX );
221+ if (bufsize == -1 ) {
222+ bufsize = DEFAULT_BUFFER_SIZE ;
223+ }
224+
225+ while (1 ) {
226+ buf2 = PyMem_RawRealloc (buf , bufsize );
227+ if (buf2 == NULL ) {
228+ nomem = 1 ;
229+ break ;
230+ }
231+ buf = buf2 ;
232+ status = getpwnam_r (name , & pwd , buf , bufsize , & p );
233+ if (status != 0 ) {
234+ p = NULL ;
235+ }
236+ if (p != NULL || status != ERANGE ) {
237+ break ;
238+ }
239+ if (bufsize > (PY_SSIZE_T_MAX >> 1 )) {
240+ nomem = 1 ;
241+ break ;
242+ }
243+ bufsize <<= 1 ;
244+ }
245+
246+ Py_END_ALLOW_THREADS
247+ #else
248+ p = getpwnam (name );
249+ #endif
250+ if (p == NULL ) {
251+ if (nomem == 1 ) {
252+ PyErr_NoMemory ();
253+ }
254+ else {
255+ PyErr_Format (PyExc_KeyError ,
256+ "getpwnam(): name not found: %s" , name );
257+ }
167258 goto out ;
168259 }
169260 retval = mkpwent (p );
170261out :
262+ PyMem_RawFree (buf );
171263 Py_DECREF (bytes );
172264 return retval ;
173265}
0 commit comments