summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lemburg <mal@egenix.com>2000-08-25 22:39:50 +0000
committerMarc-André Lemburg <mal@egenix.com>2000-08-25 22:39:50 +0000
commit6ef68b5b01c7898624b8baa5d042522d3d6532af (patch)
tree95768f88220923479c0c7563d8aebd9176a1e389
parent4ea8d6e52ebd87267e58c14fdabefcb58a1d3770 (diff)
downloadcpython-git-6ef68b5b01c7898624b8baa5d042522d3d6532af.tar.gz
Fix to bug [ Bug #111860 ] file.writelines() crashes.
file.writelines() now tries to emulate the behaviour of file.write() as closely as possible. Due to the problems with releasing the interpreter lock the solution isn't exactly optimal, but still better than not supporting the file.write() semantics at all.
-rw-r--r--Objects/fileobject.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index a7391e6ba8..8966f8cac8 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -980,8 +980,7 @@ file_writelines(PyFileObject *f, PyObject *args)
line = PySequence_GetItem(args, index+j);
if (line == NULL) {
if (PyErr_ExceptionMatches(
- PyExc_IndexError))
- {
+ PyExc_IndexError)) {
PyErr_Clear();
break;
}
@@ -989,23 +988,49 @@ file_writelines(PyFileObject *f, PyObject *args)
XXX We may lose some output. */
goto error;
}
- if (!PyString_Check(line)) {
- Py_DECREF(line);
- PyErr_SetString(PyExc_TypeError,
- "writelines() requires sequences of strings");
- goto error;
- }
PyList_SetItem(list, j, line);
}
}
if (j == 0)
break;
+ /* Check that all entries are indeed strings. If not,
+ apply the same rules as for file.write() and
+ convert the results to strings. This is slow, but
+ seems to be the only way since all conversion APIs
+ could potentially execute Python code. */
+ for (i = 0; i < j; i++) {
+ PyObject *v = PyList_GET_ITEM(list, i);
+ if (!PyString_Check(v)) {
+ const char *buffer;
+ int len;
+ if (((f->f_binary &&
+ PyObject_AsReadBuffer(v,
+ (const void**)&buffer,
+ &len)) ||
+ PyObject_AsCharBuffer(v,
+ &buffer,
+ &len))) {
+ PyErr_SetString(PyExc_TypeError,
+ "writelines() requires sequences of strings");
+ goto error;
+ }
+ line = PyString_FromStringAndSize(buffer,
+ len);
+ if (line == NULL)
+ goto error;
+ Py_DECREF(v);
+ PyList_SET_ITEM(list, i, v);
+ }
+ }
+
+ /* Since we are releasing the global lock, the
+ following code may *not* execute Python code. */
Py_BEGIN_ALLOW_THREADS
f->f_softspace = 0;
errno = 0;
for (i = 0; i < j; i++) {
- line = PyList_GET_ITEM(list, i);
+ line = PyList_GET_ITEM(list, i);
len = PyString_GET_SIZE(line);
nwritten = fwrite(PyString_AS_STRING(line),
1, len, f->f_fp);