David Watson added the comment:
Here are the alternative patches to allow more than two calls to
confstr(). One patch set just keeps reallocating the buffer
until it's big enough, while the other makes a limited number of
attempts (in this case 20) before raising RuntimeError.
----------
keywords: +patch
Added file: http://bugs.python.org/file37428/confstr-realloc-endless-2.7.diff
Added file: http://bugs.python.org/file37429/confstr-realloc-endless-3.4.diff
Added file: http://bugs.python.org/file37430/confstr-realloc-endless-3.5.diff
Added file: http://bugs.python.org/file37431/confstr-realloc-limited-2.7.diff
Added file: http://bugs.python.org/file37432/confstr-realloc-limited-3.4.diff
Added file: http://bugs.python.org/file37433/confstr-realloc-limited-3.5.diff
_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue9647>
_______________________________________
# 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,24 @@ 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;
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) {
+ 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 +7964,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
# HG changeset patch
# Parent aba5f771f5ec9e4004c0375ab4302f246a04bae7
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -9727,33 +9727,38 @@ posix_confstr(PyObject *self, PyObject *
PyObject *result = NULL;
int name;
char buffer[255];
+ char *recvbuf = buffer;
+ char *allocated = NULL;
+ size_t buflen = sizeof(buffer);
size_t len;
if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
return NULL;
- 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) {
+ 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)) {
- char *buf = PyMem_Malloc(len);
- if (buf == NULL)
- return PyErr_NoMemory();
- confstr(name, buf, len);
- result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
- PyMem_Free(buf);
+ result = Py_None;
+ Py_INCREF(Py_None);
+ }
}
else
- result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
+ result = PyUnicode_DecodeFSDefaultAndSize(recvbuf, len-1);
+finally:
+ PyMem_Free(allocated);
return result;
}
#endif
# 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,35 @@ 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));
+ /* Reset errno before each call as we may need to check it afterwards */
+ while (errno = 0, (len = confstr(name, recvbuf, buflen)) > buflen) {
+ 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 */
# 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
# HG changeset patch
# Parent aba5f771f5ec9e4004c0375ab4302f246a04bae7
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -9727,33 +9727,46 @@ posix_confstr(PyObject *self, PyObject *
PyObject *result = NULL;
int name;
char buffer[255];
+ 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))
return NULL;
- 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();
- return NULL;
}
else {
- Py_RETURN_NONE;
- }
- }
-
- if (len >= sizeof(buffer)) {
- char *buf = PyMem_Malloc(len);
- if (buf == NULL)
- return PyErr_NoMemory();
- confstr(name, buf, len);
- result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
- PyMem_Free(buf);
+ result = Py_None;
+ Py_INCREF(Py_None);
+ }
}
else
- result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
+ result = PyUnicode_DecodeFSDefaultAndSize(recvbuf, len-1);
+finally:
+ PyMem_Free(allocated);
return result;
}
#endif
# 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 */
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com