Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 19288c2

Browse files
author
Kristján Valur Jónsson
committed
Fix an issue in the tokenizer, where a file is opened by fd, but the underlying PyFileIO object wasn created with the closefd attribute true.
Also fix error handling for close() int _fileio.c . It was incorrect, looking for a negative refcount, and so errors weren't raised. This is why this issue wasn't caught. There is a second reason why it isn't seen: Class IOBase in io.py has a try:/except: around the close() funtion in the __del__() method. This also masks these error conditions. This issue was discovered by removing the _set_invalid_parameter_handler() fiddling, thus enabling the C runtime checks on windows.
1 parent baa4546 commit 19288c2

2 files changed

Lines changed: 18 additions & 16 deletions

File tree

Modules/_fileio.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,27 @@ PyTypeObject PyFileIO_Type;
5555

5656
#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
5757

58-
/* Returns 0 on success, errno (which is < 0) on failure. */
58+
/* Returns 0 on success, -1 with exception set on failure. */
5959
static int
6060
internal_close(PyFileIOObject *self)
6161
{
62-
int save_errno = 0;
62+
int err = 0;
63+
int save_errno;
6364
if (self->fd >= 0) {
6465
int fd = self->fd;
6566
self->fd = -1;
6667
Py_BEGIN_ALLOW_THREADS
67-
if (close(fd) < 0)
68+
err = close(fd);
69+
if (err < 0)
6870
save_errno = errno;
6971
Py_END_ALLOW_THREADS
7072
}
71-
return save_errno;
73+
if (err < 0) {
74+
errno = save_errno;
75+
PyErr_SetFromErrno(PyExc_IOError);
76+
return -1;
77+
}
78+
return 0;
7279
}
7380

7481
static PyObject *
@@ -78,11 +85,8 @@ fileio_close(PyFileIOObject *self)
7885
self->fd = -1;
7986
Py_RETURN_NONE;
8087
}
81-
errno = internal_close(self);
82-
if (errno < 0) {
83-
PyErr_SetFromErrno(PyExc_IOError);
88+
if (internal_close(self))
8489
return NULL;
85-
}
8690

8791
Py_RETURN_NONE;
8892
}
@@ -121,7 +125,8 @@ dircheck(PyFileIOObject* self)
121125
if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
122126
char *msg = strerror(EISDIR);
123127
PyObject *exc;
124-
internal_close(self);
128+
if (internal_close(self))
129+
return -1;
125130

126131
exc = PyObject_CallFunction(PyExc_IOError, "(is)",
127132
EISDIR, msg);
@@ -306,11 +311,8 @@ fileio_dealloc(PyFileIOObject *self)
306311
PyObject_ClearWeakRefs((PyObject *) self);
307312

308313
if (self->fd >= 0 && self->closefd) {
309-
errno = internal_close(self);
310-
if (errno < 0) {
311-
PySys_WriteStderr("close failed: [Errno %d] %s\n",
312-
errno, strerror(errno));
313-
}
314+
if(internal_close(self))
315+
PyErr_WriteUnraisable((PyObject*)self);
314316
}
315317

316318
Py_TYPE(self)->tp_free((PyObject *)self);

Parser/tokenizer.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,8 @@ fp_setreadl(struct tok_state *tok, const char* enc)
452452
stream = PyObject_CallMethod(io, "open", "ssis",
453453
tok->filename, "r", -1, enc);
454454
else
455-
stream = PyObject_CallMethod(io, "open", "isis",
456-
fileno(tok->fp), "r", -1, enc);
455+
stream = PyObject_CallMethod(io, "open", "isisOOO",
456+
fileno(tok->fp), "r", -1, enc, Py_None, Py_None, Py_False);
457457
if (stream == NULL)
458458
goto cleanup;
459459

0 commit comments

Comments
 (0)