# HG changeset patch # Parent 1edff7001f589dffaf8de4aebcb65a1f1d7deb5c diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7936,12 +7936,32 @@ posix_confstr(PyObject *self, PyObject * PyObject *result = NULL; int name; char buffer[256]; + char *recvbuf = buffer; + char *allocated = NULL; + size_t buflen = sizeof(buffer); + size_t len; + const int max_attempts = 20; + int attempts_remaining = max_attempts; if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) { - int len; - - errno = 0; - len = confstr(name, buffer, sizeof(buffer)); + + /* Reset errno before each call as we may need to check it afterwards */ + while (errno = 0, (len = confstr(name, recvbuf, buflen)) > buflen) { + if (--attempts_remaining <= 0) { + PyErr_Format(PyExc_RuntimeError, + "confstr() made %d consecutive requests for a larger " + "buffer; giving up", max_attempts); + goto finally; + } + recvbuf = PyMem_Realloc(allocated, len); + if (recvbuf == NULL) { + PyErr_NoMemory(); + goto finally; + } + allocated = recvbuf; + buflen = len; + } + if (len == 0) { if (errno) { posix_error(); @@ -7952,15 +7972,11 @@ posix_confstr(PyObject *self, PyObject * } } else { - if ((unsigned int)len >= sizeof(buffer)) { - result = PyString_FromStringAndSize(NULL, len-1); - if (result != NULL) - confstr(name, PyString_AS_STRING(result), len); - } - else - result = PyString_FromStringAndSize(buffer, len-1); - } - } + result = PyString_FromStringAndSize(recvbuf, len-1); + } + } +finally: + PyMem_Free(allocated); return result; } #endif