# HG changeset patch # Parent 5754f069b12342acb69dff739782416092522748 diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -14372,32 +14372,43 @@ os_confstr_impl(PyModuleDef *module, int { PyObject *result = NULL; char buffer[255]; + char *recvbuf = buffer; + char *allocated = NULL; + size_t buflen = sizeof(buffer); size_t len; - - errno = 0; - len = confstr(name, buffer, sizeof(buffer)); + const int max_attempts = 20; + int attempts_remaining = max_attempts; + + /* 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(); - return NULL; } else { - Py_RETURN_NONE; - } - } - - if (len >= sizeof(buffer)) { - size_t len2; - char *buf = PyMem_Malloc(len); - if (buf == NULL) - return PyErr_NoMemory(); - len2 = confstr(name, buf, len); - assert(len == len2); - result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1); - PyMem_Free(buf); - } - else - result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); + result = Py_None; + Py_INCREF(Py_None); + } + } + else + result = PyUnicode_DecodeFSDefaultAndSize(recvbuf, len-1); +finally: + PyMem_Free(allocated); return result; } #endif /* HAVE_CONFSTR */