mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
[3.12] gh-107913: Fix possible losses of OSError error codes (GH-107930) (#108523)
gh-107913: Fix possible losses of OSError error codes (GH-107930)
Functions like PyErr_SetFromErrno() and SetFromWindowsErr() should be
called immediately after using the C API which sets errno or the Windows
error code.
(cherry picked from commit 2b15536fa9
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
bbdd8895a5
commit
3e20303717
17 changed files with 129 additions and 75 deletions
|
@ -3877,9 +3877,10 @@ posix_getcwd(int use_bytes)
|
|||
return NULL;
|
||||
}
|
||||
if (!len) {
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
if (wbuf2 != wbuf)
|
||||
PyMem_RawFree(wbuf2);
|
||||
return PyErr_SetFromWindowsErr(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
|
||||
|
@ -3927,8 +3928,9 @@ posix_getcwd(int use_bytes)
|
|||
return PyErr_NoMemory();
|
||||
}
|
||||
if (cwd == NULL) {
|
||||
posix_error();
|
||||
PyMem_RawFree(buf);
|
||||
return posix_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *obj;
|
||||
|
@ -4140,8 +4142,8 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list)
|
|||
int error = GetLastError();
|
||||
if (error == ERROR_FILE_NOT_FOUND)
|
||||
goto exit;
|
||||
Py_DECREF(list);
|
||||
list = path_error(path);
|
||||
path_error(path);
|
||||
Py_CLEAR(list);
|
||||
goto exit;
|
||||
}
|
||||
do {
|
||||
|
@ -4154,12 +4156,12 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list)
|
|||
Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
|
||||
}
|
||||
if (v == NULL) {
|
||||
Py_SETREF(list, NULL);
|
||||
Py_CLEAR(list);
|
||||
break;
|
||||
}
|
||||
if (PyList_Append(list, v) != 0) {
|
||||
Py_DECREF(v);
|
||||
Py_SETREF(list, NULL);
|
||||
Py_CLEAR(list);
|
||||
break;
|
||||
}
|
||||
Py_DECREF(v);
|
||||
|
@ -4170,8 +4172,8 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list)
|
|||
/* FindNextFile sets error to ERROR_NO_MORE_FILES if
|
||||
it got to the end of the directory. */
|
||||
if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
|
||||
Py_DECREF(list);
|
||||
list = path_error(path);
|
||||
path_error(path);
|
||||
Py_CLEAR(list);
|
||||
goto exit;
|
||||
}
|
||||
} while (result == TRUE);
|
||||
|
@ -4180,8 +4182,8 @@ exit:
|
|||
if (hFindFile != INVALID_HANDLE_VALUE) {
|
||||
if (FindClose(hFindFile) == FALSE) {
|
||||
if (list != NULL) {
|
||||
Py_DECREF(list);
|
||||
list = path_error(path);
|
||||
path_error(path);
|
||||
Py_CLEAR(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4243,7 +4245,8 @@ _posix_listdir(path_t *path, PyObject *list)
|
|||
}
|
||||
|
||||
if (dirp == NULL) {
|
||||
list = path_error(path);
|
||||
path_error(path);
|
||||
list = NULL;
|
||||
#ifdef HAVE_FDOPENDIR
|
||||
if (fd != -1) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
@ -4265,8 +4268,8 @@ _posix_listdir(path_t *path, PyObject *list)
|
|||
if (errno == 0) {
|
||||
break;
|
||||
} else {
|
||||
Py_DECREF(list);
|
||||
list = path_error(path);
|
||||
path_error(path);
|
||||
Py_CLEAR(list);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
@ -6609,8 +6612,9 @@ os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
|
|||
|
||||
/* If we get here it's definitely an error */
|
||||
|
||||
posix_error();
|
||||
free_string_array(argvlist, argc);
|
||||
return posix_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -6914,11 +6918,12 @@ parse_file_actions(PyObject *file_actions,
|
|||
}
|
||||
errno = posix_spawn_file_actions_addopen(file_actionsp,
|
||||
fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
|
||||
Py_DECREF(path);
|
||||
if (errno) {
|
||||
posix_error();
|
||||
Py_DECREF(path);
|
||||
goto fail;
|
||||
}
|
||||
Py_DECREF(path);
|
||||
break;
|
||||
}
|
||||
case POSIX_SPAWN_CLOSE: {
|
||||
|
@ -7315,12 +7320,15 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
|
|||
_Py_END_SUPPRESS_IPH
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
int saved_errno = errno;
|
||||
free_string_array(argvlist, argc);
|
||||
|
||||
if (spawnval == -1)
|
||||
return posix_error();
|
||||
else
|
||||
return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
|
||||
if (spawnval == -1) {
|
||||
errno = saved_errno;
|
||||
posix_error();
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
|
@ -7638,6 +7646,7 @@ os_fork1_impl(PyObject *module)
|
|||
}
|
||||
PyOS_BeforeFork();
|
||||
pid = fork1();
|
||||
int saved_errno = errno;
|
||||
if (pid == 0) {
|
||||
/* child: this clobbers and resets the import lock. */
|
||||
PyOS_AfterFork_Child();
|
||||
|
@ -7646,8 +7655,10 @@ os_fork1_impl(PyObject *module)
|
|||
/* parent: release the import lock. */
|
||||
PyOS_AfterFork_Parent();
|
||||
}
|
||||
if (pid == -1)
|
||||
if (pid == -1) {
|
||||
errno = saved_errno;
|
||||
return posix_error();
|
||||
}
|
||||
return PyLong_FromPid(pid);
|
||||
}
|
||||
#endif /* HAVE_FORK1 */
|
||||
|
@ -7683,6 +7694,7 @@ os_fork_impl(PyObject *module)
|
|||
}
|
||||
PyOS_BeforeFork();
|
||||
pid = fork();
|
||||
int saved_errno = errno;
|
||||
if (pid == 0) {
|
||||
/* child: this clobbers and resets the import lock. */
|
||||
PyOS_AfterFork_Child();
|
||||
|
@ -7691,8 +7703,10 @@ os_fork_impl(PyObject *module)
|
|||
/* parent: release the import lock. */
|
||||
PyOS_AfterFork_Parent();
|
||||
}
|
||||
if (pid == -1)
|
||||
if (pid == -1) {
|
||||
errno = saved_errno;
|
||||
return posix_error();
|
||||
}
|
||||
return PyLong_FromPid(pid);
|
||||
}
|
||||
#endif /* HAVE_FORK */
|
||||
|
@ -8229,13 +8243,17 @@ os_openpty_impl(PyObject *module)
|
|||
|
||||
/* change permission of slave */
|
||||
if (grantpt(master_fd) < 0) {
|
||||
int saved_errno = errno;
|
||||
PyOS_setsig(SIGCHLD, sig_saved);
|
||||
errno = saved_errno;
|
||||
goto posix_error;
|
||||
}
|
||||
|
||||
/* unlock slave */
|
||||
if (unlockpt(master_fd) < 0) {
|
||||
int saved_errno = errno;
|
||||
PyOS_setsig(SIGCHLD, sig_saved);
|
||||
errno = saved_errno;
|
||||
goto posix_error;
|
||||
}
|
||||
|
||||
|
@ -8599,8 +8617,9 @@ os_getgroups_impl(PyObject *module)
|
|||
|
||||
n = getgroups(n, grouplist);
|
||||
if (n == -1) {
|
||||
posix_error();
|
||||
PyMem_Free(grouplist);
|
||||
return posix_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *result = PyList_New(n);
|
||||
|
@ -9163,8 +9182,9 @@ os_setgroups(PyObject *module, PyObject *groups)
|
|||
}
|
||||
|
||||
if (setgroups(len, grouplist) < 0) {
|
||||
posix_error();
|
||||
PyMem_Free(grouplist);
|
||||
return posix_error();
|
||||
return NULL;
|
||||
}
|
||||
PyMem_Free(grouplist);
|
||||
Py_RETURN_NONE;
|
||||
|
@ -10611,10 +10631,13 @@ os_readv_impl(PyObject *module, int fd, PyObject *buffers)
|
|||
Py_END_ALLOW_THREADS
|
||||
} while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
|
||||
int saved_errno = errno;
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
if (n < 0) {
|
||||
if (!async_err)
|
||||
if (!async_err) {
|
||||
errno = saved_errno;
|
||||
posix_error();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -10663,8 +10686,11 @@ os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
|
|||
} while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
|
||||
if (n < 0) {
|
||||
if (!async_err) {
|
||||
posix_error();
|
||||
}
|
||||
Py_DECREF(buffer);
|
||||
return (!async_err) ? posix_error() : NULL;
|
||||
return NULL;
|
||||
}
|
||||
if (n != length)
|
||||
_PyBytes_Resize(&buffer, n);
|
||||
|
@ -10761,9 +10787,11 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
|
|||
|
||||
#endif
|
||||
|
||||
int saved_errno = errno;
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
if (n < 0) {
|
||||
if (!async_err) {
|
||||
errno = saved_errno;
|
||||
posix_error();
|
||||
}
|
||||
return -1;
|
||||
|
@ -10932,24 +10960,26 @@ os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
|
|||
} while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
_Py_END_SUPPRESS_IPH
|
||||
|
||||
int saved_errno = errno;
|
||||
if (sf.headers != NULL)
|
||||
iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
|
||||
if (sf.trailers != NULL)
|
||||
iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
|
||||
|
||||
if (ret < 0) {
|
||||
if ((errno == EAGAIN) || (errno == EBUSY)) {
|
||||
if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
|
||||
if (sbytes != 0) {
|
||||
// some data has been sent
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
// no data has been sent; upper application is supposed
|
||||
// to retry on EAGAIN or EBUSY
|
||||
return posix_error();
|
||||
}
|
||||
// no data has been sent; upper application is supposed
|
||||
// to retry on EAGAIN or EBUSY
|
||||
}
|
||||
return (!async_err) ? posix_error() : NULL;
|
||||
if (!async_err) {
|
||||
errno = saved_errno;
|
||||
posix_error();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
goto done;
|
||||
|
||||
|
@ -11266,10 +11296,10 @@ os_writev_impl(PyObject *module, int fd, PyObject *buffers)
|
|||
Py_END_ALLOW_THREADS
|
||||
} while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
if (result < 0 && !async_err)
|
||||
posix_error();
|
||||
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
return result;
|
||||
}
|
||||
#endif /* HAVE_WRITEV */
|
||||
|
@ -11404,13 +11434,13 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
|
|||
|
||||
#endif
|
||||
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
if (result < 0) {
|
||||
if (!async_err) {
|
||||
posix_error();
|
||||
}
|
||||
return -1;
|
||||
result = -1;
|
||||
}
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -11972,12 +12002,13 @@ win32_putenv(PyObject *name, PyObject *value)
|
|||
Prefer _wputenv() to be compatible with C libraries using CRT
|
||||
variables and CRT functions using these variables (ex: getenv()). */
|
||||
int err = _wputenv(env);
|
||||
PyMem_Free(env);
|
||||
|
||||
if (err) {
|
||||
posix_error();
|
||||
PyMem_Free(env);
|
||||
return NULL;
|
||||
}
|
||||
PyMem_Free(env);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -13819,10 +13850,12 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
|
|||
Py_END_ALLOW_THREADS;
|
||||
|
||||
if (result < 0) {
|
||||
Py_DECREF(buffer);
|
||||
if (errno == ERANGE)
|
||||
if (errno == ERANGE) {
|
||||
Py_DECREF(buffer);
|
||||
continue;
|
||||
}
|
||||
path_error(path);
|
||||
Py_DECREF(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -14589,14 +14622,19 @@ DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
|
|||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
|
||||
int saved_errno = errno;
|
||||
#if defined(MS_WINDOWS)
|
||||
PyMem_Free(path);
|
||||
#else
|
||||
Py_DECREF(ub);
|
||||
#endif
|
||||
|
||||
if (result != 0)
|
||||
return path_object_error(self->path);
|
||||
if (result != 0) {
|
||||
errno = saved_errno;
|
||||
path_object_error(self->path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _pystat_fromstructstat(module, &st);
|
||||
}
|
||||
|
@ -14788,10 +14826,14 @@ os_DirEntry_inode_impl(DirEntry *self)
|
|||
wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
|
||||
Py_DECREF(unicode);
|
||||
result = LSTAT(path, &stat);
|
||||
|
||||
int saved_errno = errno;
|
||||
PyMem_Free(path);
|
||||
|
||||
if (result != 0)
|
||||
if (result != 0) {
|
||||
errno = saved_errno;
|
||||
return path_object_error(self->path);
|
||||
}
|
||||
|
||||
self->win32_file_index = stat.st_ino;
|
||||
self->got_file_index = 1;
|
||||
|
@ -15355,12 +15397,12 @@ os_scandir_impl(PyObject *module, path_t *path)
|
|||
iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
PyMem_Free(path_strW);
|
||||
|
||||
if (iterator->handle == INVALID_HANDLE_VALUE) {
|
||||
path_error(&iterator->path);
|
||||
PyMem_Free(path_strW);
|
||||
goto error;
|
||||
}
|
||||
PyMem_Free(path_strW);
|
||||
#else /* POSIX */
|
||||
errno = 0;
|
||||
#ifdef HAVE_FDOPENDIR
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue