Commit 1dd82a95 authored by Victor Stinner's avatar Victor Stinner

Issue #23694: Enhance _Py_fopen(), it now raises an exception on error

* If fopen() fails, OSError is raised with the original filename object.
* The GIL is now released while calling fopen()
parent 39710881
...@@ -2941,11 +2941,9 @@ load_dh_params(PySSLContext *self, PyObject *filepath) ...@@ -2941,11 +2941,9 @@ load_dh_params(PySSLContext *self, PyObject *filepath)
DH *dh; DH *dh;
f = _Py_fopen_obj(filepath, "rb"); f = _Py_fopen_obj(filepath, "rb");
if (f == NULL) { if (f == NULL)
if (!PyErr_Occurred())
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath);
return NULL; return NULL;
}
errno = 0; errno = 0;
PySSL_BEGIN_ALLOW_THREADS PySSL_BEGIN_ALLOW_THREADS
dh = PEM_read_DHparams(f, NULL, NULL, NULL); dh = PEM_read_DHparams(f, NULL, NULL, NULL);
......
...@@ -875,7 +875,7 @@ read_directory(PyObject *archive) ...@@ -875,7 +875,7 @@ read_directory(PyObject *archive)
fp = _Py_fopen_obj(archive, "rb"); fp = _Py_fopen_obj(archive, "rb");
if (fp == NULL) { if (fp == NULL) {
if (!PyErr_Occurred()) if (PyErr_ExceptionMatches(PyExc_OSError))
PyErr_Format(ZipImportError, "can't open Zip file: %R", archive); PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
return NULL; return NULL;
} }
...@@ -1073,12 +1073,8 @@ get_data(PyObject *archive, PyObject *toc_entry) ...@@ -1073,12 +1073,8 @@ get_data(PyObject *archive, PyObject *toc_entry)
} }
fp = _Py_fopen_obj(archive, "rb"); fp = _Py_fopen_obj(archive, "rb");
if (!fp) { if (!fp)
if (!PyErr_Occurred())
PyErr_Format(PyExc_IOError,
"zipimport: can not open file %U", archive);
return NULL; return NULL;
}
/* Check to make sure the local file header is correct */ /* Check to make sure the local file header is correct */
if (fseek(fp, file_offset, 0) == -1) { if (fseek(fp, file_offset, 0) == -1) {
......
...@@ -1126,6 +1126,10 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno) ...@@ -1126,6 +1126,10 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno)
if (filename == NULL || lineno <= 0) if (filename == NULL || lineno <= 0)
return NULL; return NULL;
fp = _Py_fopen_obj(filename, "r" PY_STDIOTEXTMODE); fp = _Py_fopen_obj(filename, "r" PY_STDIOTEXTMODE);
if (fp == NULL) {
PyErr_Clear();
return NULL;
}
return err_programtext(fp, lineno); return err_programtext(fp, lineno);
} }
......
...@@ -957,7 +957,7 @@ _Py_open_impl(const char *pathname, int flags, int gil_held) ...@@ -957,7 +957,7 @@ _Py_open_impl(const char *pathname, int flags, int gil_held)
The file descriptor is created non-inheritable. The file descriptor is created non-inheritable.
The GIL must be held. Use _Py_open_noraise() if the GIL cannot be held. */ The GIL must be held. */
int int
_Py_open(const char *pathname, int flags) _Py_open(const char *pathname, int flags)
{ {
...@@ -977,8 +977,9 @@ _Py_open_noraise(const char *pathname, int flags) ...@@ -977,8 +977,9 @@ _Py_open_noraise(const char *pathname, int flags)
} }
/* Open a file. Use _wfopen() on Windows, encode the path to the locale /* Open a file. Use _wfopen() on Windows, encode the path to the locale
encoding and use fopen() otherwise. The file descriptor is created encoding and use fopen() otherwise.
non-inheritable. */
The file descriptor is created non-inheritable). */
FILE * FILE *
_Py_wfopen(const wchar_t *path, const wchar_t *mode) _Py_wfopen(const wchar_t *path, const wchar_t *mode)
{ {
...@@ -1009,7 +1010,9 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode) ...@@ -1009,7 +1010,9 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
return f; return f;
} }
/* Wrapper to fopen(). The file descriptor is created non-inheritable. */ /* Wrapper to fopen().
The file descriptor is created non-inheritable). */
FILE* FILE*
_Py_fopen(const char *pathname, const char *mode) _Py_fopen(const char *pathname, const char *mode)
{ {
...@@ -1024,11 +1027,14 @@ _Py_fopen(const char *pathname, const char *mode) ...@@ -1024,11 +1027,14 @@ _Py_fopen(const char *pathname, const char *mode)
} }
/* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem /* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
encoding and call fopen() otherwise. The file descriptor is created encoding and call fopen() otherwise.
non-inheritable.
Return the new file object on success. Raise an exception and return NULL
on error.
Return the new file object on success, or NULL if the file cannot be open or The file descriptor is created non-inheritable.
(if PyErr_Occurred()) on unicode error. */
The GIL must be held. */
FILE* FILE*
_Py_fopen_obj(PyObject *path, const char *mode) _Py_fopen_obj(PyObject *path, const char *mode)
{ {
...@@ -1038,6 +1044,8 @@ _Py_fopen_obj(PyObject *path, const char *mode) ...@@ -1038,6 +1044,8 @@ _Py_fopen_obj(PyObject *path, const char *mode)
wchar_t wmode[10]; wchar_t wmode[10];
int usize; int usize;
assert(PyGILState_Check());
if (!PyUnicode_Check(path)) { if (!PyUnicode_Check(path)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"str file path expected under Windows, got %R", "str file path expected under Windows, got %R",
...@@ -1049,20 +1057,36 @@ _Py_fopen_obj(PyObject *path, const char *mode) ...@@ -1049,20 +1057,36 @@ _Py_fopen_obj(PyObject *path, const char *mode)
return NULL; return NULL;
usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
if (usize == 0) if (usize == 0) {
PyErr_SetFromWindowsErr(0);
return NULL; return NULL;
}
Py_BEGIN_ALLOW_THREADS
f = _wfopen(wpath, wmode); f = _wfopen(wpath, wmode);
Py_END_ALLOW_THREADS
#else #else
PyObject *bytes; PyObject *bytes;
char *path_bytes;
assert(PyGILState_Check());
if (!PyUnicode_FSConverter(path, &bytes)) if (!PyUnicode_FSConverter(path, &bytes))
return NULL; return NULL;
f = fopen(PyBytes_AS_STRING(bytes), mode); path_bytes = PyBytes_AS_STRING(bytes);
Py_BEGIN_ALLOW_THREADS
f = fopen(path_bytes, mode);
Py_END_ALLOW_THREADS
Py_DECREF(bytes); Py_DECREF(bytes);
#endif #endif
if (f == NULL) if (f == NULL) {
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
return NULL; return NULL;
if (make_non_inheritable(fileno(f)) < 0) { }
if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {
fclose(f); fclose(f);
return NULL; return NULL;
} }
......
...@@ -1945,8 +1945,6 @@ _imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyOb ...@@ -1945,8 +1945,6 @@ _imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyOb
fp = _Py_fopen_obj(path, "r"); fp = _Py_fopen_obj(path, "r");
if (fp == NULL) { if (fp == NULL) {
Py_DECREF(path); Py_DECREF(path);
if (!PyErr_Occurred())
PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment