diff --git a/Lib/logging/config.py b/Lib/logging/config.py index e39dac432f6ab5c..35233e731eb42d1 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -21,7 +21,7 @@ Copyright (C) 2001-2022 Vinay Sajip. All Rights Reserved. -To use, simply 'import logging' and log away! +To use, simply 'import logging.config' and log away! """ import errno diff --git a/Lib/pydoc.py b/Lib/pydoc.py index ca4eb1001981681..fe42592530c2cfd 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1355,7 +1355,7 @@ def docmodule(self, object, name=None, mod=None, *ignored): if data: contents = [] for key, value in data: - contents.append(self.docother(value, key, name, maxlen=70)) + contents.append(self.docother(value, key, name, maxlen=76)) result = result + self.section('DATA', '\n'.join(contents)) if version := self._get_version(object): @@ -1478,7 +1478,7 @@ def spilldata(msg, attrs, predicate): obj = getattr(object, name) except AttributeError: obj = homecls.__dict__[name] - push(self.docother(obj, name, mod, maxlen=70, doc=doc) + + push(self.docother(obj, name, mod, maxlen=72, doc=doc) + '\n') return attrs @@ -1629,7 +1629,7 @@ def docother(self, object, name=None, mod=None, parent=None, *ignored, if maxlen: line = (name and name + ' = ' or '') + repr chop = maxlen - len(line) - if chop < 0: repr = repr[:chop] + '...' + if chop < 0: repr = repr[:chop-3] + '...' line = (name and self.bold(name) + ' = ' or '') + repr if not doc: doc = getdoc(object) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-05-31-22.gh-issue-151065._o_31F.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-05-31-22.gh-issue-151065._o_31F.rst new file mode 100644 index 000000000000000..e46c96ef784cc9e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-05-31-22.gh-issue-151065._o_31F.rst @@ -0,0 +1 @@ +Fix memory leak when using the :ref:`mimalloc memory allocator `. diff --git a/Misc/NEWS.d/next/Library/2026-06-11-19-46-16.gh-issue-150285.wuhAsL.rst b/Misc/NEWS.d/next/Library/2026-06-11-19-46-16.gh-issue-150285.wuhAsL.rst new file mode 100644 index 000000000000000..3f19150488f3131 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-11-19-46-16.gh-issue-150285.wuhAsL.rst @@ -0,0 +1,2 @@ +:mod:`pydoc` now uses all available space (80 columns) for formatting reprs +of module and class data, but ensure that they do not overflow. diff --git a/Misc/NEWS.d/next/Library/2026-06-11-21-43-24.gh-issue-151337.JSVV18.rst b/Misc/NEWS.d/next/Library/2026-06-11-21-43-24.gh-issue-151337.JSVV18.rst new file mode 100644 index 000000000000000..0344eee9471d292 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-11-21-43-24.gh-issue-151337.JSVV18.rst @@ -0,0 +1 @@ +Avoid possible memory leak in ``tkinter.c`` on Windows. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 58fdabecf16ada7..6eca98a3c8033fa 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -128,18 +128,20 @@ _get_tcl_lib_path(void) } /* Check expected location for an installed Python first */ - tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION); - if (tcl_library_path == NULL) { + PyObject* tmp_tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION); + if (tmp_tcl_library_path == NULL) { Py_DECREF(prefix); return NULL; } - tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path); + tcl_library_path = PyUnicode_Concat(prefix, tmp_tcl_library_path); + Py_DECREF(tmp_tcl_library_path); Py_DECREF(prefix); if (tcl_library_path == NULL) { return NULL; } stat_return_value = _Py_stat(tcl_library_path, &stat_buf); if (stat_return_value == -2) { + Py_DECREF(tcl_library_path); return NULL; } if (stat_return_value == -1) { @@ -154,16 +156,17 @@ _get_tcl_lib_path(void) } stat_return_value = _Py_stat(tcl_library_path, &stat_buf); if (stat_return_value == -2) { + Py_DECREF(tcl_library_path); return NULL; } if (stat_return_value == -1) { /* tcltkDir for a repository build doesn't exist either, reset errno and leave Tcl to its own devices */ errno = 0; - tcl_library_path = NULL; + Py_CLEAR(tcl_library_path); } #else - tcl_library_path = NULL; + Py_CLEAR(tcl_library_path); #endif } already_checked = 1; @@ -707,11 +710,13 @@ Tkapp_New(const char *screenName, const char *className, if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { str_path = _get_tcl_lib_path(); if (str_path == NULL && PyErr_Occurred()) { + Py_DECREF(v); return NULL; } if (str_path != NULL) { utf8_path = PyUnicode_AsUTF8String(str_path); if (utf8_path == NULL) { + Py_DECREF(v); return NULL; } Tcl_SetVar(v->interp, diff --git a/Objects/mimalloc/init.c b/Objects/mimalloc/init.c index 81b241063ff40fc..7711c827a58b1ca 100644 --- a/Objects/mimalloc/init.c +++ b/Objects/mimalloc/init.c @@ -183,9 +183,9 @@ mi_heap_t* _mi_heap_main_get(void) { // note: in x64 in release build `sizeof(mi_thread_data_t)` is under 4KiB (= OS page size). typedef struct mi_thread_data_s { - mi_heap_t heap; // must come first due to cast in `_mi_heap_done` + mi_heap_t heap; // must come first due to cast in `_mi_heap_done` mi_tld_t tld; - mi_memid_t memid; + mi_memid_t memid; // must come last due to zero'ing } mi_thread_data_t; @@ -231,7 +231,7 @@ static mi_thread_data_t* mi_thread_data_zalloc(void) { } if (td != NULL && !is_zero) { - _mi_memzero_aligned(td, sizeof(*td)); + _mi_memzero_aligned(td, offsetof(mi_thread_data_t,memid)); } return td; }