Skip to content

Commit 3e20303

Browse files
[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 2b15536) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent bbdd889 commit 3e20303

17 files changed

+129
-75
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix possible losses of ``errno`` and ``winerror`` values in :exc:`OSError`
2+
exceptions if they were cleared or modified by the cleanup code before
3+
creating the exception object.

Modules/_cursesmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3071,8 +3071,8 @@ _curses_getwin(PyObject *module, PyObject *file)
30713071
}
30723072
datalen = PyBytes_GET_SIZE(data);
30733073
if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) {
3074-
Py_DECREF(data);
30753074
PyErr_SetFromErrno(PyExc_OSError);
3075+
Py_DECREF(data);
30763076
goto error;
30773077
}
30783078
Py_DECREF(data);

Modules/_io/fileio.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,11 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
394394

395395
if (async_err)
396396
goto error;
397+
398+
if (self->fd < 0) {
399+
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj);
400+
goto error;
401+
}
397402
}
398403
else {
399404
PyObject *fdobj;
@@ -425,12 +430,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
425430
goto error;
426431
}
427432
}
428-
429433
fd_is_own = 1;
430-
if (self->fd < 0) {
431-
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj);
432-
goto error;
433-
}
434434

435435
#ifndef MS_WINDOWS
436436
if (_Py_set_inheritable(self->fd, 0, atomic_flag_works) < 0)
@@ -1058,8 +1058,8 @@ _io_FileIO_truncate_impl(fileio *self, PyTypeObject *cls, PyObject *posobj)
10581058
Py_END_ALLOW_THREADS
10591059

10601060
if (ret != 0) {
1061-
Py_DECREF(posobj);
10621061
PyErr_SetFromErrno(PyExc_OSError);
1062+
Py_DECREF(posobj);
10631063
return NULL;
10641064
}
10651065

Modules/_io/winconsoleio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,8 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
378378
else
379379
self->fd = _Py_open_osfhandle_noraise(handle, _O_RDONLY | _O_BINARY);
380380
if (self->fd < 0) {
381-
CloseHandle(handle);
382381
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj);
382+
CloseHandle(handle);
383383
goto error;
384384
}
385385
}

Modules/_localemodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,8 @@ _locale_bindtextdomain_impl(PyObject *module, const char *domain,
737737
}
738738
current_dirname = bindtextdomain(domain, dirname);
739739
if (current_dirname == NULL) {
740-
Py_XDECREF(dirname_bytes);
741740
PyErr_SetFromErrno(PyExc_OSError);
741+
Py_XDECREF(dirname_bytes);
742742
return NULL;
743743
}
744744
result = PyUnicode_DecodeLocale(current_dirname, NULL);

Modules/_multiprocessing/semaphore.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -516,12 +516,12 @@ _multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value,
516516
return result;
517517

518518
failure:
519-
if (handle != SEM_FAILED)
520-
SEM_CLOSE(handle);
521-
PyMem_Free(name_copy);
522519
if (!PyErr_Occurred()) {
523520
_PyMp_SetError(NULL, MP_STANDARD_ERROR);
524521
}
522+
if (handle != SEM_FAILED)
523+
SEM_CLOSE(handle);
524+
PyMem_Free(name_copy);
525525
return NULL;
526526
}
527527

@@ -556,8 +556,9 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
556556
if (name != NULL) {
557557
handle = sem_open(name, 0);
558558
if (handle == SEM_FAILED) {
559+
PyErr_SetFromErrno(PyExc_OSError);
559560
PyMem_Free(name_copy);
560-
return PyErr_SetFromErrno(PyExc_OSError);
561+
return NULL;
561562
}
562563
}
563564
#endif

Modules/_ssl.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,8 +3889,8 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
38893889
/* the password callback has already set the error information */
38903890
}
38913891
else if (errno != 0) {
3892-
ERR_clear_error();
38933892
PyErr_SetFromErrno(PyExc_OSError);
3893+
ERR_clear_error();
38943894
}
38953895
else {
38963896
_setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__);
@@ -3910,8 +3910,8 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
39103910
/* the password callback has already set the error information */
39113911
}
39123912
else if (errno != 0) {
3913-
ERR_clear_error();
39143913
PyErr_SetFromErrno(PyExc_OSError);
3914+
ERR_clear_error();
39153915
}
39163916
else {
39173917
_setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__);
@@ -4140,8 +4140,8 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
41404140
PySSL_END_ALLOW_THREADS
41414141
if (r != 1) {
41424142
if (errno != 0) {
4143-
ERR_clear_error();
41444143
PyErr_SetFromErrno(PyExc_OSError);
4144+
ERR_clear_error();
41454145
}
41464146
else {
41474147
_setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__);
@@ -4188,8 +4188,8 @@ _ssl__SSLContext_load_dh_params(PySSLContext *self, PyObject *filepath)
41884188
PySSL_END_ALLOW_THREADS
41894189
if (dh == NULL) {
41904190
if (errno != 0) {
4191-
ERR_clear_error();
41924191
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath);
4192+
ERR_clear_error();
41934193
}
41944194
else {
41954195
_setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__);

Modules/faulthandler.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,11 +414,10 @@ faulthandler_allocate_stack(void)
414414

415415
int err = sigaltstack(&stack, &old_stack);
416416
if (err) {
417+
PyErr_SetFromErrno(PyExc_OSError);
417418
/* Release the stack to retry sigaltstack() next time */
418419
PyMem_Free(stack.ss_sp);
419420
stack.ss_sp = NULL;
420-
421-
PyErr_SetFromErrno(PyExc_OSError);
422421
return -1;
423422
}
424423
return 0;

Modules/fcntlmodule.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,12 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code,
211211
if (mutate_arg && (len <= IOCTL_BUFSZ)) {
212212
memcpy(str, buf, len);
213213
}
214-
PyBuffer_Release(&pstr); /* No further access to str below this point */
215214
if (ret < 0) {
216215
PyErr_SetFromErrno(PyExc_OSError);
216+
PyBuffer_Release(&pstr);
217217
return NULL;
218218
}
219+
PyBuffer_Release(&pstr);
219220
if (mutate_arg) {
220221
return PyLong_FromLong(ret);
221222
}
@@ -240,8 +241,8 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code,
240241
ret = ioctl(fd, code, buf);
241242
Py_END_ALLOW_THREADS
242243
if (ret < 0) {
243-
PyBuffer_Release(&pstr);
244244
PyErr_SetFromErrno(PyExc_OSError);
245+
PyBuffer_Release(&pstr);
245246
return NULL;
246247
}
247248
PyBuffer_Release(&pstr);

Modules/getpath.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,12 @@ getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args)
341341
return NULL;
342342
}
343343
FILE *fp = _Py_wfopen(path, L"rb");
344-
PyMem_Free((void *)path);
345344
if (!fp) {
346345
PyErr_SetFromErrno(PyExc_OSError);
346+
PyMem_Free((void *)path);
347347
return NULL;
348348
}
349+
PyMem_Free((void *)path);
349350

350351
r = PyList_New(0);
351352
if (!r) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy