]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix to bug [ Bug #111860 ] file.writelines() crashes.
authorMarc-André Lemburg <mal@egenix.com>
Fri, 25 Aug 2000 22:39:50 +0000 (22:39 +0000)
committerMarc-André Lemburg <mal@egenix.com>
Fri, 25 Aug 2000 22:39:50 +0000 (22:39 +0000)
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.

Objects/fileobject.c

index a7391e6ba8d020fc426dcb4249a3c81539acbc26..8966f8cac82520a0c799c1f7b6ae05c07ca8ab95 100644 (file)
@@ -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);