diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 19cc7050a43f04..5bf60348f68250 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -260,33 +260,33 @@ Include/pyhash.h @gpshead @picnixz Python/pyhash.c @gpshead @picnixz # The import system (including importlib) -**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw -Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @kumaraditya303 +**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00 +Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00 @kumaraditya303 **/*freeze* @ericsnowcurrently **/*frozen* @ericsnowcurrently **/*modsupport* @ericsnowcurrently -**/*modulefinder* @ericsnowcurrently +**/*modulefinder* @ericsnowcurrently @FFY00 **/*moduleobject* @ericsnowcurrently **/*multiphase* @ericsnowcurrently -**/*pkgutil* @ericsnowcurrently +**/*pkgutil* @ericsnowcurrently @FFY00 **/*pythonrun* @ericsnowcurrently -**/*runpy* @ericsnowcurrently +**/*runpy* @ericsnowcurrently @FFY00 **/*singlephase* @ericsnowcurrently Doc/c-api/module.rst @ericsnowcurrently Lib/test/test_module/ @ericsnowcurrently -Python/dynload_*.c @ericsnowcurrently +Python/dynload_*.c @ericsnowcurrently @FFY00 # Initialisation -**/*initconfig* @ericsnowcurrently -**/*pathconfig* @ericsnowcurrently -**/*preconfig* @ericsnowcurrently +**/*initconfig* @ericsnowcurrently @FFY00 +**/*pathconfig* @ericsnowcurrently @FFY00 +**/*preconfig* @ericsnowcurrently @FFY00 Doc/library/sys_path_init.rst @FFY00 Doc/c-api/init_config.rst @FFY00 # Interpreter main program -Modules/main.c @ericsnowcurrently -Programs/_bootstrap_python.c @ericsnowcurrently -Programs/python.c @ericsnowcurrently +Modules/main.c @ericsnowcurrently @FFY00 +Programs/_bootstrap_python.c @ericsnowcurrently @FFY00 +Programs/python.c @ericsnowcurrently @FFY00 # JIT .github/workflows/jit.yml @savannahostrowski @@ -316,8 +316,8 @@ Tools/peg_generator/ @pablogsal @lysnikolaou # Runtime state/lifecycle **/*gil* @ericsnowcurrently -**/*pylifecycle* @ericsnowcurrently @ZeroIntensity -**/*pystate* @ericsnowcurrently @ZeroIntensity +**/*pylifecycle* @ericsnowcurrently @ZeroIntensity @FFY00 +**/*pystate* @ericsnowcurrently @ZeroIntensity @FFY00 Include/internal/pycore_*_init.h @ericsnowcurrently Include/internal/pycore_*_state.h @ericsnowcurrently Include/internal/pycore_atexit.h @ericsnowcurrently @@ -505,13 +505,13 @@ Lib/idlelib/ @terryjreedy Lib/turtledemo/ @terryjreedy # importlib.metadata -Doc/library/importlib.metadata.rst @jaraco @warsaw -Lib/importlib/metadata/ @jaraco @warsaw -Lib/test/test_importlib/metadata/ @jaraco @warsaw +Doc/library/importlib.metadata.rst @jaraco @warsaw @FFY00 +Lib/importlib/metadata/ @jaraco @warsaw @FFY00 +Lib/test/test_importlib/metadata/ @jaraco @warsaw @FFY00 # importlib.resources -Doc/library/importlib.resources.abc.rst @jaraco @warsaw -Doc/library/importlib.resources.rst @jaraco @warsaw +Doc/library/importlib.resources.abc.rst @jaraco @warsaw @FFY00 +Doc/library/importlib.resources.rst @jaraco @warsaw @FFY00 Lib/importlib/resources/ @jaraco @warsaw @FFY00 Lib/test/test_importlib/resources/ @jaraco @warsaw @FFY00 diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 7418f3a8bacb0f..a22afdec516bb4 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2409,6 +2409,10 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: next + ``os.listdir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing the current directory. + .. function:: listdrives() @@ -2939,6 +2943,10 @@ features: .. versionchanged:: 3.7 Added support for :ref:`file descriptors ` on Unix. + .. versionchanged:: next + ``os.scandir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing the current directory. + .. class:: DirEntry @@ -4574,6 +4582,10 @@ These functions are all available on Linux only. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: next + ``os.listxattr(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing extended attributes of the current directory. + .. function:: removexattr(path, attribute, *, follow_symlinks=True) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 4451d485884987..76a4367dd2dcd5 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4536,7 +4536,7 @@ copying. types such as :class:`bytes` and :class:`bytearray`, an element is a single byte, but other types such as :class:`array.array` may have bigger elements. - ``len(view)`` is equal to the length of :class:`~memoryview.tolist`, which + ``len(view)`` is equal to the length of :meth:`~memoryview.tolist`, which is the nested list representation of the view. If ``view.ndim = 1``, this is equal to the number of elements in the view. diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 6e61a1a44ad232..ff020b52da3f23 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -181,11 +181,21 @@ Wave_write Objects Set the number of channels. + .. method:: getnchannels() + + Return the number of channels. + + .. method:: setsampwidth(n) Set the sample width to *n* bytes. + .. method:: getsampwidth() + + Return the sample width in bytes. + + .. method:: setframerate(n) Set the frame rate to *n*. @@ -195,6 +205,11 @@ Wave_write Objects integer. + .. method:: getframerate() + + Return the frame rate. + + .. method:: setnframes(n) Set the number of frames to *n*. This will be changed later if the number @@ -202,12 +217,27 @@ Wave_write Objects raise an error if the output stream is not seekable). + .. method:: getnframes() + + Return the number of audio frames written so far. + + .. method:: setcomptype(type, name) Set the compression type and description. At the moment, only compression type ``NONE`` is supported, meaning no compression. + .. method:: getcomptype() + + Return the compression type (``'NONE'``). + + + .. method:: getcompname() + + Return the human-readable compression type name. + + .. method:: setparams(tuple) The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype, @@ -215,6 +245,13 @@ Wave_write Objects parameters. + .. method:: getparams() + + Return a :func:`~collections.namedtuple` + ``(nchannels, sampwidth, framerate, nframes, comptype, compname)`` + containing the current output parameters. + + .. method:: tell() Return current position in the file, with the same disclaimer for the diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 86652b7fa4d6df..dda42cb33072c3 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -514,6 +514,58 @@ def test_partial_genericalias(self): self.assertEqual(alias.__args__, (int,)) self.assertEqual(alias.__parameters__, ()) + # GH-144475: Tests that the partial object does not change until repr finishes + def test_repr_safety_against_reentrant_mutation(self): + g_partial = None + + class Function: + def __init__(self, name): + self.name = name + + def __call__(self): + return None + + def __repr__(self): + return f"Function({self.name})" + + class EvilObject: + def __init__(self): + self.triggered = False + + def __repr__(self): + if not self.triggered and g_partial is not None: + self.triggered = True + new_args_tuple = (None,) + new_keywords_dict = {"keyword": None} + new_tuple_state = (Function("new_function"), new_args_tuple, new_keywords_dict, None) + g_partial.__setstate__(new_tuple_state) + gc.collect() + return f"EvilObject" + + trigger = EvilObject() + func = Function("old_function") + + g_partial = functools.partial(func, None, trigger=trigger) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), None, trigger=EvilObject)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, arg=None)") + + + trigger.triggered = False + g_partial = functools.partial(func, trigger, None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, None)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger=trigger, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), trigger=EvilObject, arg=None)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger, None, None, None, None, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, None, None, None, None, arg=None)") + + @unittest.skipUnless(c_functools, 'requires the C _functools module') class TestPartialC(TestPartial, unittest.TestCase): diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 5d30ec2299789b..a4180f05dbbafc 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -12,6 +12,7 @@ import os from test import support +from test.support.script_helper import assert_python_ok try: import _testcapi @@ -219,6 +220,16 @@ def test_lazy_import_type_cant_construct(self): """LazyImportType should not be directly constructible.""" self.assertRaises(TypeError, types.LazyImportType, {}, "module") + @support.requires_subprocess() + def test_lazy_import_type_attributes_accessible(self): + """Check that static PyLazyImport_Type is initialized at startup.""" + code = textwrap.dedent(""" + lazy import json + print(globals()["json"].resolve) + """) + proc = assert_python_ok("-c", code) + self.assertIn(b"fn); + PyObject *args = Py_NewRef(pto->args); + PyObject *kw = Py_NewRef(pto->kw); + assert(PyTuple_Check(args)); + assert(PyDict_Check(kw)); arglist = Py_GetConstant(Py_CONSTANT_EMPTY_STR); - if (arglist == NULL) + if (arglist == NULL) { goto done; + } /* Pack positional arguments */ - assert(PyTuple_Check(pto->args)); - n = PyTuple_GET_SIZE(pto->args); + n = PyTuple_GET_SIZE(args); for (i = 0; i < n; i++) { Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist, - PyTuple_GET_ITEM(pto->args, i))); - if (arglist == NULL) + PyTuple_GET_ITEM(args, i))); + if (arglist == NULL) { goto done; + } } /* Pack keyword arguments */ - assert (PyDict_Check(pto->kw)); - for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) { + for (i = 0; PyDict_Next(kw, &i, &key, &value);) { /* Prevent key.__str__ from deleting the value. */ Py_INCREF(value); Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist, key, value)); Py_DECREF(value); - if (arglist == NULL) + if (arglist == NULL) { goto done; + } } mod = PyType_GetModuleName(Py_TYPE(pto)); if (mod == NULL) { - goto error; + goto done; } + name = PyType_GetQualName(Py_TYPE(pto)); if (name == NULL) { - Py_DECREF(mod); - goto error; + goto done; } - result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, pto->fn, arglist); - Py_DECREF(mod); - Py_DECREF(name); - Py_DECREF(arglist); - done: + result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, fn, arglist); +done: + Py_XDECREF(name); + Py_XDECREF(mod); + Py_XDECREF(arglist); + Py_DECREF(fn); + Py_DECREF(args); + Py_DECREF(kw); Py_ReprLeave(self); return result; - error: - Py_DECREF(arglist); - Py_ReprLeave(self); - return NULL; } /* Pickle strategy: diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index 0cbe10c79ab4a6..14da472c1bb110 100644 --- a/Modules/_xxtestfuzz/fuzzer.c +++ b/Modules/_xxtestfuzz/fuzzer.c @@ -428,6 +428,7 @@ static int fuzz_ast_literal_eval(const char* data, size_t size) { PyErr_ExceptionMatches(PyExc_TypeError) || PyErr_ExceptionMatches(PyExc_SyntaxError) || PyErr_ExceptionMatches(PyExc_MemoryError) || + PyErr_ExceptionMatches(PyExc_OverflowError) || PyErr_ExceptionMatches(PyExc_RecursionError)) ) { PyErr_Clear(); diff --git a/Modules/main.c b/Modules/main.c index 74e48c94732565..95ba541d98c2e8 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -506,6 +506,7 @@ pymain_run_interactive_hook(int *exitcode) } if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) { + Py_DECREF(hook); goto error; } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index b82f08e7dc4291..aa3d682a19bc9c 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1638,10 +1638,10 @@ dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) } static int -fd_and_follow_symlinks_invalid(const char *function_name, int fd, +fd_and_follow_symlinks_invalid(const char *function_name, int is_fd, int follow_symlinks) { - if ((fd >= 0) && (!follow_symlinks)) { + if (is_fd && (!follow_symlinks)) { PyErr_Format(PyExc_ValueError, "%s: cannot use fd and follow_symlinks together", function_name); @@ -2880,12 +2880,13 @@ posix_do_stat(PyObject *module, const char *function_name, path_t *path, if (path_and_dir_fd_invalid("stat", path, dir_fd) || dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks)) return NULL; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) + if (path->is_fd) { result = FSTAT(path->fd, &st); + } #ifdef MS_WINDOWS else if (follow_symlinks) result = win32_stat(path->wide, &st); @@ -3647,7 +3648,7 @@ os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags, { if (path_and_dir_fd_invalid("statx", path, dir_fd) || dir_fd_and_fd_invalid("statx", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) { + fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) { return NULL; } @@ -3677,7 +3678,7 @@ os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags, int result; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx); } else { @@ -3934,7 +3935,7 @@ os_chdir_impl(PyObject *module, path_t *path) result = !win32_wchdir(path->wide); #else #ifdef HAVE_FCHDIR - if (path->fd != -1) + if (path->is_fd) result = fchdir(path->fd); else #endif @@ -4090,7 +4091,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, #ifdef MS_WINDOWS result = 0; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = win32_fchmod(path->fd, mode); } else if (follow_symlinks) { @@ -4113,8 +4114,9 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHMOD - if (path->fd != -1) + if (path->is_fd) { result = fchmod(path->fd, mode); + } else #endif /* HAVE_CHMOD */ #ifdef HAVE_LCHMOD @@ -4511,7 +4513,7 @@ os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, return NULL; #endif if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, @@ -4521,7 +4523,7 @@ os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHOWN - if (path->fd != -1) + if (path->is_fd) result = fchown(path->fd, uid, gid); else #endif @@ -4999,7 +5001,7 @@ _posix_listdir(path_t *path, PyObject *list) errno = 0; #ifdef HAVE_FDOPENDIR - if (path->fd != -1) { + if (path->is_fd) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ fd = _Py_dup(path->fd); @@ -5898,7 +5900,7 @@ _testFileExists(path_t *path, BOOL followLinks) } Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) { @@ -5924,7 +5926,7 @@ _testFileType(path_t *path, int testedType) } Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { result = _testFileTypeByHandle(hfile, testedType, TRUE); @@ -7141,7 +7143,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, if (path_and_dir_fd_invalid("utime", path, dir_fd) || dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks)) return NULL; #if !defined(HAVE_UTIMENSAT) @@ -7200,7 +7202,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #endif #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) - if (path->fd != -1) + if (path->is_fd) result = utime_fd(&utime, path->fd); else #endif @@ -7569,7 +7571,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_FEXECVE - if (path->fd > -1) + if (path->is_fd) fexecve(path->fd, argvlist, envlist); else #endif @@ -13355,7 +13357,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) int fd; #endif - if (path->fd != -1) + if (path->is_fd) return os_ftruncate_impl(module, path->fd, length); if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { @@ -14052,7 +14054,7 @@ os_statvfs_impl(PyObject *module, path_t *path) struct statfs st; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = fstatfs(path->fd, &st); } else @@ -14070,7 +14072,7 @@ os_statvfs_impl(PyObject *module, path_t *path) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FSTATVFS - if (path->fd != -1) { + if (path->is_fd) { result = fstatvfs(path->fd, &st); } else @@ -15410,7 +15412,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks) /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ { - if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { @@ -15432,7 +15434,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, void *ptr = PyBytesWriter_GetData(writer); Py_BEGIN_ALLOW_THREADS; - if (path->fd >= 0) + if (path->is_fd) result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); else if (follow_symlinks) result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); @@ -15481,7 +15483,7 @@ os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, { ssize_t result; - if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, @@ -15490,7 +15492,7 @@ os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) result = fsetxattr(path->fd, attribute->narrow, value->buf, value->len, flags); else if (follow_symlinks) @@ -15534,7 +15536,7 @@ os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, { ssize_t result; - if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { @@ -15542,7 +15544,7 @@ os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) result = fremovexattr(path->fd, attribute->narrow); else if (follow_symlinks) result = removexattr(path->narrow, attribute->narrow); @@ -15584,7 +15586,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) const char *name; char *buffer = NULL; - if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks)) goto exit; if (PySys_Audit("os.listxattr", "(O)", @@ -15611,7 +15613,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) length = flistxattr(path->fd, buffer, buffer_size); else if (follow_symlinks) length = listxattr(name, buffer, buffer_size); @@ -16664,7 +16666,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, entry->stat = NULL; entry->lstat = NULL; - if (path->fd != -1) { + if (path->is_fd) { entry->dir_fd = path->fd; joined_path = NULL; } @@ -16689,7 +16691,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, if (!entry->name) goto error; - if (path->fd != -1) { + if (path->is_fd) { entry->path = Py_NewRef(entry->name); } else if (!entry->path) @@ -16813,8 +16815,9 @@ ScandirIterator_closedir(ScandirIterator *iterator) iterator->dirp = NULL; Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) + if (iterator->path.is_fd) { rewinddir(dirp); + } #endif closedir(dirp); Py_END_ALLOW_THREADS @@ -17034,7 +17037,7 @@ os_scandir_impl(PyObject *module, path_t *path) #else /* POSIX */ errno = 0; #ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) { + if (iterator->path.is_fd) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ fd = _Py_dup(iterator->path.fd); diff --git a/Objects/object.c b/Objects/object.c index ab73d2eb1c9c1f..b537c0d104e58c 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -17,6 +17,7 @@ #include "pycore_instruction_sequence.h" // _PyInstructionSequence_Type #include "pycore_interpframe.h" // _PyFrame_Stackbase() #include "pycore_interpolation.h" // _PyInterpolation_Type +#include "pycore_lazyimportobject.h" // PyLazyImport_Type #include "pycore_list.h" // _PyList_DebugMallocStats() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_memoryobject.h" // _PyManagedBuffer_Type @@ -2540,6 +2541,7 @@ static PyTypeObject* static_types[] = { &PyGen_Type, &PyGetSetDescr_Type, &PyInstanceMethod_Type, + &PyLazyImport_Type, &PyListIter_Type, &PyListRevIter_Type, &PyList_Type, diff --git a/Python/crossinterp.c b/Python/crossinterp.c index 6365b995a0d3f7..c8a80e7a986008 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -609,6 +609,7 @@ check_missing___main___attr(PyObject *exc) // Get the error message. PyObject *args = PyException_GetArgs(exc); if (args == NULL || args == Py_None || PyObject_Size(args) < 1) { + Py_XDECREF(args); assert(!PyErr_Occurred()); return 0; } diff --git a/Python/import.c b/Python/import.c index dfc4d5707bfdba..3ed808f67f4149 100644 --- a/Python/import.c +++ b/Python/import.c @@ -5642,6 +5642,7 @@ _imp__set_lazy_attributes_impl(PyObject *module, PyObject *modobj, module_dict = get_mod_dict(modobj); if (module_dict == NULL || !PyDict_CheckExact(module_dict)) { + Py_DECREF(lazy_submodules); goto done; } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index ec8c2d12ab27fc..043bdf3433ab57 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1145,6 +1145,7 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) "traceback", "_print_exception_bltin"); if (print_exception_fn == NULL || !PyCallable_Check(print_exception_fn)) { + Py_XDECREF(print_exception_fn); goto fallback; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 28b2108940c853..55b4072213d3c2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1762,7 +1762,7 @@ sys_getwindowsversion_impl(PyObject *module) PyObject *realVersion = _sys_getwindowsversion_from_kernel32(); if (!realVersion) { if (!PyErr_ExceptionMatches(PyExc_WindowsError)) { - return NULL; + goto error; } PyErr_Clear();