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

Skip to content

Commit e42ccd2

Browse files
committed
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()
1 parent a555cfc commit e42ccd2

5 files changed

Lines changed: 44 additions & 24 deletions

File tree

Modules/_ssl.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2941,11 +2941,9 @@ load_dh_params(PySSLContext *self, PyObject *filepath)
29412941
DH *dh;
29422942

29432943
f = _Py_fopen_obj(filepath, "rb");
2944-
if (f == NULL) {
2945-
if (!PyErr_Occurred())
2946-
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath);
2944+
if (f == NULL)
29472945
return NULL;
2948-
}
2946+
29492947
errno = 0;
29502948
PySSL_BEGIN_ALLOW_THREADS
29512949
dh = PEM_read_DHparams(f, NULL, NULL, NULL);

Modules/zipimport.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ read_directory(PyObject *archive)
875875

876876
fp = _Py_fopen_obj(archive, "rb");
877877
if (fp == NULL) {
878-
if (!PyErr_Occurred())
878+
if (PyErr_ExceptionMatches(PyExc_OSError))
879879
PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
880880
return NULL;
881881
}
@@ -1073,12 +1073,8 @@ get_data(PyObject *archive, PyObject *toc_entry)
10731073
}
10741074

10751075
fp = _Py_fopen_obj(archive, "rb");
1076-
if (!fp) {
1077-
if (!PyErr_Occurred())
1078-
PyErr_Format(PyExc_IOError,
1079-
"zipimport: can not open file %U", archive);
1076+
if (!fp)
10801077
return NULL;
1081-
}
10821078

10831079
/* Check to make sure the local file header is correct */
10841080
if (fseek(fp, file_offset, 0) == -1) {

Python/errors.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,10 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno)
11261126
if (filename == NULL || lineno <= 0)
11271127
return NULL;
11281128
fp = _Py_fopen_obj(filename, "r" PY_STDIOTEXTMODE);
1129+
if (fp == NULL) {
1130+
PyErr_Clear();
1131+
return NULL;
1132+
}
11291133
return err_programtext(fp, lineno);
11301134
}
11311135

Python/fileutils.c

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,7 @@ _Py_open_impl(const char *pathname, int flags, int gil_held)
957957
958958
The file descriptor is created non-inheritable.
959959
960-
The GIL must be held. Use _Py_open_noraise() if the GIL cannot be held. */
960+
The GIL must be held. */
961961
int
962962
_Py_open(const char *pathname, int flags)
963963
{
@@ -977,8 +977,9 @@ _Py_open_noraise(const char *pathname, int flags)
977977
}
978978

979979
/* Open a file. Use _wfopen() on Windows, encode the path to the locale
980-
encoding and use fopen() otherwise. The file descriptor is created
981-
non-inheritable. */
980+
encoding and use fopen() otherwise.
981+
982+
The file descriptor is created non-inheritable). */
982983
FILE *
983984
_Py_wfopen(const wchar_t *path, const wchar_t *mode)
984985
{
@@ -1009,7 +1010,9 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
10091010
return f;
10101011
}
10111012

1012-
/* Wrapper to fopen(). The file descriptor is created non-inheritable. */
1013+
/* Wrapper to fopen().
1014+
1015+
The file descriptor is created non-inheritable). */
10131016
FILE*
10141017
_Py_fopen(const char *pathname, const char *mode)
10151018
{
@@ -1024,11 +1027,14 @@ _Py_fopen(const char *pathname, const char *mode)
10241027
}
10251028

10261029
/* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
1027-
encoding and call fopen() otherwise. The file descriptor is created
1028-
non-inheritable.
1030+
encoding and call fopen() otherwise.
1031+
1032+
Return the new file object on success. Raise an exception and return NULL
1033+
on error.
10291034
1030-
Return the new file object on success, or NULL if the file cannot be open or
1031-
(if PyErr_Occurred()) on unicode error. */
1035+
The file descriptor is created non-inheritable.
1036+
1037+
The GIL must be held. */
10321038
FILE*
10331039
_Py_fopen_obj(PyObject *path, const char *mode)
10341040
{
@@ -1038,6 +1044,8 @@ _Py_fopen_obj(PyObject *path, const char *mode)
10381044
wchar_t wmode[10];
10391045
int usize;
10401046

1047+
assert(PyGILState_Check());
1048+
10411049
if (!PyUnicode_Check(path)) {
10421050
PyErr_Format(PyExc_TypeError,
10431051
"str file path expected under Windows, got %R",
@@ -1049,20 +1057,36 @@ _Py_fopen_obj(PyObject *path, const char *mode)
10491057
return NULL;
10501058

10511059
usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
1052-
if (usize == 0)
1060+
if (usize == 0) {
1061+
PyErr_SetFromWindowsErr(0);
10531062
return NULL;
1063+
}
10541064

1065+
Py_BEGIN_ALLOW_THREADS
10551066
f = _wfopen(wpath, wmode);
1067+
Py_END_ALLOW_THREADS
10561068
#else
10571069
PyObject *bytes;
1070+
char *path_bytes;
1071+
1072+
assert(PyGILState_Check());
1073+
10581074
if (!PyUnicode_FSConverter(path, &bytes))
10591075
return NULL;
1060-
f = fopen(PyBytes_AS_STRING(bytes), mode);
1076+
path_bytes = PyBytes_AS_STRING(bytes);
1077+
1078+
Py_BEGIN_ALLOW_THREADS
1079+
f = fopen(path_bytes, mode);
1080+
Py_END_ALLOW_THREADS
1081+
10611082
Py_DECREF(bytes);
10621083
#endif
1063-
if (f == NULL)
1084+
if (f == NULL) {
1085+
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
10641086
return NULL;
1065-
if (make_non_inheritable(fileno(f)) < 0) {
1087+
}
1088+
1089+
if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {
10661090
fclose(f);
10671091
return NULL;
10681092
}

Python/import.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,8 +1945,6 @@ _imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyOb
19451945
fp = _Py_fopen_obj(path, "r");
19461946
if (fp == NULL) {
19471947
Py_DECREF(path);
1948-
if (!PyErr_Occurred())
1949-
PyErr_SetFromErrno(PyExc_IOError);
19501948
return NULL;
19511949
}
19521950
}

0 commit comments

Comments
 (0)