summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshadchin <[email protected]>2026-02-07 19:56:35 +0300
committershadchin <[email protected]>2026-02-07 20:23:53 +0300
commit19d43a3e6fb4cb8ea11747d7d7bca7a3542fbb44 (patch)
tree0b1418938140a0b6470953bef6069454ffdf1bd0
parent0879409bfc0891ab8103828a3bdbf0e960475fec (diff)
Update Python 3 to 3.13.12
commit_hash:71d3efea437a769b2b7910d196120bb02587046e
-rw-r--r--contrib/tools/python3/.yandex_meta/override.nix4
-rw-r--r--contrib/tools/python3/Include/cpython/object.h12
-rw-r--r--contrib/tools/python3/Include/cpython/pyerrors.h1
-rw-r--r--contrib/tools/python3/Include/internal/pycore_ceval.h2
-rw-r--r--contrib/tools/python3/Include/internal/pycore_ceval_state.h3
-rw-r--r--contrib/tools/python3/Include/internal/pycore_pymath.h6
-rw-r--r--contrib/tools/python3/Include/patchlevel.h4
-rw-r--r--contrib/tools/python3/Lib/_android_support.py7
-rw-r--r--contrib/tools/python3/Lib/_pyio.py26
-rw-r--r--contrib/tools/python3/Lib/_pyrepl/unix_console.py7
-rw-r--r--contrib/tools/python3/Lib/_pyrepl/windows_console.py18
-rw-r--r--contrib/tools/python3/Lib/_sitebuiltins.py24
-rw-r--r--contrib/tools/python3/Lib/argparse.py46
-rw-r--r--contrib/tools/python3/Lib/asyncio/__main__.py18
-rw-r--r--contrib/tools/python3/Lib/asyncio/futures.py4
-rw-r--r--contrib/tools/python3/Lib/asyncio/selector_events.py12
-rw-r--r--contrib/tools/python3/Lib/email/_encoded_words.py2
-rw-r--r--contrib/tools/python3/Lib/email/_header_value_parser.py50
-rw-r--r--contrib/tools/python3/Lib/email/feedparser.py7
-rw-r--r--contrib/tools/python3/Lib/email/generator.py12
-rw-r--r--contrib/tools/python3/Lib/email/headerregistry.py14
-rw-r--r--contrib/tools/python3/Lib/enum.py3
-rw-r--r--contrib/tools/python3/Lib/hmac.py1
-rw-r--r--contrib/tools/python3/Lib/http/cookies.py25
-rw-r--r--contrib/tools/python3/Lib/inspect.py2
-rw-r--r--contrib/tools/python3/Lib/linecache.py67
-rw-r--r--contrib/tools/python3/Lib/logging/handlers.py6
-rw-r--r--contrib/tools/python3/Lib/mailbox.py6
-rw-r--r--contrib/tools/python3/Lib/multiprocessing/forkserver.py7
-rw-r--r--contrib/tools/python3/Lib/multiprocessing/spawn.py2
-rwxr-xr-xcontrib/tools/python3/Lib/pdb.py32
-rw-r--r--contrib/tools/python3/Lib/plistlib.py2
-rwxr-xr-xcontrib/tools/python3/Lib/pydoc.py19
-rw-r--r--contrib/tools/python3/Lib/pydoc_data/module_docs.py314
-rw-r--r--contrib/tools/python3/Lib/pydoc_data/topics.py134
-rw-r--r--contrib/tools/python3/Lib/ssl.py2
-rw-r--r--contrib/tools/python3/Lib/stat.py11
-rw-r--r--contrib/tools/python3/Lib/subprocess.py2
-rw-r--r--contrib/tools/python3/Lib/types.py4
-rw-r--r--contrib/tools/python3/Lib/typing.py4
-rw-r--r--contrib/tools/python3/Lib/unittest/mock.py2
-rw-r--r--contrib/tools/python3/Lib/urllib/request.py5
-rw-r--r--contrib/tools/python3/Lib/wsgiref/headers.py3
-rw-r--r--contrib/tools/python3/Lib/xml/dom/minidom.py2
-rw-r--r--contrib/tools/python3/Lib/ya.make5
-rw-r--r--contrib/tools/python3/Lib/zoneinfo/_common.py9
-rw-r--r--contrib/tools/python3/Modules/_collectionsmodule.c15
-rw-r--r--contrib/tools/python3/Modules/_ctypes/_ctypes.c9
-rw-r--r--contrib/tools/python3/Modules/_decimal/_decimal.c16
-rw-r--r--contrib/tools/python3/Modules/_elementtree.c40
-rw-r--r--contrib/tools/python3/Modules/_io/bufferedio.c4
-rw-r--r--contrib/tools/python3/Modules/_io/bytesio.c16
-rw-r--r--contrib/tools/python3/Modules/_io/textio.c3
-rw-r--r--contrib/tools/python3/Modules/_json.c3
-rw-r--r--contrib/tools/python3/Modules/_pickle.c186
-rw-r--r--contrib/tools/python3/Modules/_sqlite/connection.c88
-rw-r--r--contrib/tools/python3/Modules/_sqlite/connection.h1
-rw-r--r--contrib/tools/python3/Modules/_sqlite/ya.make4
-rw-r--r--contrib/tools/python3/Modules/_struct.c27
-rw-r--r--contrib/tools/python3/Modules/_zoneinfo.c16
-rw-r--r--contrib/tools/python3/Modules/arraymodule.c65
-rw-r--r--contrib/tools/python3/Modules/atexitmodule.c7
-rw-r--r--contrib/tools/python3/Modules/overlapped.c6
-rw-r--r--contrib/tools/python3/Modules/posixmodule.c47
-rw-r--r--contrib/tools/python3/Modules/socketmodule.c5
-rw-r--r--contrib/tools/python3/Objects/bytearrayobject.c136
-rw-r--r--contrib/tools/python3/Objects/call.c1
-rw-r--r--contrib/tools/python3/Objects/dictobject.c7
-rw-r--r--contrib/tools/python3/Objects/exceptions.c90
-rw-r--r--contrib/tools/python3/Objects/floatobject.c79
-rw-r--r--contrib/tools/python3/Objects/genericaliasobject.c7
-rw-r--r--contrib/tools/python3/Objects/genobject.c4
-rw-r--r--contrib/tools/python3/Objects/longobject.c4
-rw-r--r--contrib/tools/python3/Objects/memoryobject.c21
-rw-r--r--contrib/tools/python3/Objects/object.c2
-rw-r--r--contrib/tools/python3/Objects/setobject.c3
-rw-r--r--contrib/tools/python3/Objects/typeobject.c18
-rw-r--r--contrib/tools/python3/Objects/typevarobject.c4
-rw-r--r--contrib/tools/python3/PC/winreg.c2
-rw-r--r--contrib/tools/python3/Parser/pegen_errors.c2
-rw-r--r--contrib/tools/python3/Python/Python-ast.c4
-rw-r--r--contrib/tools/python3/Python/ceval.c6
-rw-r--r--contrib/tools/python3/Python/context.c12
-rw-r--r--contrib/tools/python3/Python/crossinterp.c16
-rw-r--r--contrib/tools/python3/Python/errors.c6
-rw-r--r--contrib/tools/python3/Python/frozen_modules/_sitebuiltins.h216
-rw-r--r--contrib/tools/python3/Python/frozen_modules/stat.h318
-rw-r--r--contrib/tools/python3/Python/hamt.c27
-rw-r--r--contrib/tools/python3/Python/import.c11
-rw-r--r--contrib/tools/python3/Python/initconfig.c4
-rw-r--r--contrib/tools/python3/Python/marshal.c4
-rw-r--r--contrib/tools/python3/Python/perf_jit_trampoline.c4
-rw-r--r--contrib/tools/python3/Python/perf_trampoline.c68
-rw-r--r--contrib/tools/python3/Python/pylifecycle.c2
-rw-r--r--contrib/tools/python3/Python/pystate.c8
-rw-r--r--contrib/tools/python3/Python/sysmodule.c23
-rw-r--r--contrib/tools/python3/Python/traceback.c3
-rw-r--r--contrib/tools/python3/README.rst2
-rw-r--r--contrib/tools/python3/bin/ya.make4
-rw-r--r--contrib/tools/python3/lib2/py/ya.make1
-rw-r--r--contrib/tools/python3/ya.make4
101 files changed, 1833 insertions, 796 deletions
diff --git a/contrib/tools/python3/.yandex_meta/override.nix b/contrib/tools/python3/.yandex_meta/override.nix
index 9ee7dd4cf11..f0e7c00a7ea 100644
--- a/contrib/tools/python3/.yandex_meta/override.nix
+++ b/contrib/tools/python3/.yandex_meta/override.nix
@@ -1,11 +1,11 @@
pkgs: attrs: with pkgs; with attrs; rec {
- version = "3.13.11";
+ version = "3.13.12";
src = fetchFromGitHub {
owner = "python";
repo = "cpython";
rev = "v${version}";
- hash = "sha256-SS0ZDQSwIRJPulUad5uG5vWLg6eGZNAYlvNdYx6mQPA=";
+ hash = "sha256-m1j3U3QVsISgENCkxoNZPbTJWW8IO86/s5KRWNoY2DA=";
};
patches = [];
diff --git a/contrib/tools/python3/Include/cpython/object.h b/contrib/tools/python3/Include/cpython/object.h
index 6cb2c40fe2e..5b3b890dcf3 100644
--- a/contrib/tools/python3/Include/cpython/object.h
+++ b/contrib/tools/python3/Include/cpython/object.h
@@ -221,7 +221,9 @@ struct _typeobject {
PyObject *tp_weaklist; /* not used for static builtin types */
destructor tp_del;
- /* Type attribute cache version tag. Added in version 2.6 */
+ /* Type attribute cache version tag. Added in version 2.6.
+ * If zero, the cache is invalid and must be initialized.
+ */
unsigned int tp_version_tag;
destructor tp_finalize;
@@ -229,9 +231,17 @@ struct _typeobject {
/* bitset of which type-watchers care about this type */
unsigned char tp_watched;
+
+ /* Number of tp_version_tag values used.
+ * Set to _Py_ATTR_CACHE_UNUSED if the attribute cache is
+ * disabled for this type (e.g. due to custom MRO entries).
+ * Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere).
+ */
uint16_t tp_versions_used;
};
+#define _Py_ATTR_CACHE_UNUSED (30000) // (see tp_versions_used)
+
/* This struct is used by the specializer
* It should be treated as an opaque blob
* by code other than the specializer and interpreter. */
diff --git a/contrib/tools/python3/Include/cpython/pyerrors.h b/contrib/tools/python3/Include/cpython/pyerrors.h
index b36b4681f5d..422391c3222 100644
--- a/contrib/tools/python3/Include/cpython/pyerrors.h
+++ b/contrib/tools/python3/Include/cpython/pyerrors.h
@@ -18,6 +18,7 @@ typedef struct {
PyException_HEAD
PyObject *msg;
PyObject *excs;
+ PyObject *excs_str;
} PyBaseExceptionGroupObject;
typedef struct {
diff --git a/contrib/tools/python3/Include/internal/pycore_ceval.h b/contrib/tools/python3/Include/internal/pycore_ceval.h
index f804823cc53..41df3a34c91 100644
--- a/contrib/tools/python3/Include/internal/pycore_ceval.h
+++ b/contrib/tools/python3/Include/internal/pycore_ceval.h
@@ -105,7 +105,6 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *);
extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
extern int _PyPerfTrampoline_Init(int activate);
extern int _PyPerfTrampoline_Fini(void);
-extern void _PyPerfTrampoline_FreeArenas(void);
extern int _PyIsPerfTrampolineActive(void);
extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
#ifdef PY_HAVE_PERF_TRAMPOLINE
@@ -258,6 +257,7 @@ PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subjec
PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys);
PyAPI_FUNC(int) _PyEval_UnpackIterable(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, PyObject **sp);
PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
+PyAPI_FUNC(bool) _PyEval_NoToolsForUnwind(PyThreadState *tstate);
PyAPI_FUNC(void) _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);
diff --git a/contrib/tools/python3/Include/internal/pycore_ceval_state.h b/contrib/tools/python3/Include/internal/pycore_ceval_state.h
index 009a1ea41eb..a109c195724 100644
--- a/contrib/tools/python3/Include/internal/pycore_ceval_state.h
+++ b/contrib/tools/python3/Include/internal/pycore_ceval_state.h
@@ -90,6 +90,9 @@ struct _ceval_runtime_state {
struct trampoline_api_st trampoline_api;
FILE *map_file;
Py_ssize_t persist_after_fork;
+ _PyFrameEvalFunction prev_eval_frame;
+ Py_ssize_t trampoline_refcount;
+ int code_watcher_id;
#else
int _not_used;
#endif
diff --git a/contrib/tools/python3/Include/internal/pycore_pymath.h b/contrib/tools/python3/Include/internal/pycore_pymath.h
index 7a4e1c1eb71..12d3efc33c6 100644
--- a/contrib/tools/python3/Include/internal/pycore_pymath.h
+++ b/contrib/tools/python3/Include/internal/pycore_pymath.h
@@ -146,17 +146,17 @@ extern void _Py_set_387controlword(unsigned short);
unsigned int old_fpcr, new_fpcr
#define _Py_SET_53BIT_PRECISION_START \
do { \
- __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr)); \
+ __asm__ ("fmove.l %%fpcr,%0" : "=dm" (old_fpcr)); \
/* Set double precision / round to nearest. */ \
new_fpcr = (old_fpcr & ~0xf0) | 0x80; \
if (new_fpcr != old_fpcr) { \
- __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr));\
+ __asm__ volatile ("fmove.l %0,%%fpcr" : : "dm" (new_fpcr)); \
} \
} while (0)
#define _Py_SET_53BIT_PRECISION_END \
do { \
if (new_fpcr != old_fpcr) { \
- __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr)); \
+ __asm__ volatile ("fmove.l %0,%%fpcr" : : "dm" (old_fpcr)); \
} \
} while (0)
#endif
diff --git a/contrib/tools/python3/Include/patchlevel.h b/contrib/tools/python3/Include/patchlevel.h
index b255f96e94c..7246ff769eb 100644
--- a/contrib/tools/python3/Include/patchlevel.h
+++ b/contrib/tools/python3/Include/patchlevel.h
@@ -18,12 +18,12 @@
/*--start constants--*/
#define PY_MAJOR_VERSION 3
#define PY_MINOR_VERSION 13
-#define PY_MICRO_VERSION 11
+#define PY_MICRO_VERSION 12
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.13.11"
+#define PY_VERSION "3.13.12"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
diff --git a/contrib/tools/python3/Lib/_android_support.py b/contrib/tools/python3/Lib/_android_support.py
index a439d03a144..320dab52acd 100644
--- a/contrib/tools/python3/Lib/_android_support.py
+++ b/contrib/tools/python3/Lib/_android_support.py
@@ -168,6 +168,13 @@ class Logcat:
# message.
message = message.replace(b"\x00", b"\xc0\x80")
+ # On API level 30 and higher, Logcat will strip any number of leading
+ # newlines. This is visible in all `logcat` modes, even --binary. Work
+ # around this by adding a leading space, which shouldn't make any
+ # difference to the log's usability.
+ if message.startswith(b"\n"):
+ message = b" " + message
+
with self._lock:
now = time()
self._bucket_level += (
diff --git a/contrib/tools/python3/Lib/_pyio.py b/contrib/tools/python3/Lib/_pyio.py
index 48c8f770f81..9ed2e5b2aa0 100644
--- a/contrib/tools/python3/Lib/_pyio.py
+++ b/contrib/tools/python3/Lib/_pyio.py
@@ -941,22 +941,24 @@ class BytesIO(BufferedIOBase):
return self.read(size)
def write(self, b):
- if self.closed:
- raise ValueError("write to closed file")
if isinstance(b, str):
raise TypeError("can't write str to binary stream")
with memoryview(b) as view:
+ if self.closed:
+ raise ValueError("write to closed file")
+
n = view.nbytes # Size of any bytes-like object
- if n == 0:
- return 0
- pos = self._pos
- if pos > len(self._buffer):
- # Inserts null bytes between the current end of the file
- # and the new write position.
- padding = b'\x00' * (pos - len(self._buffer))
- self._buffer += padding
- self._buffer[pos:pos + n] = b
- self._pos += n
+ if n == 0:
+ return 0
+
+ pos = self._pos
+ if pos > len(self._buffer):
+ # Inserts null bytes between the current end of the file
+ # and the new write position.
+ padding = b'\x00' * (pos - len(self._buffer))
+ self._buffer += padding
+ self._buffer[pos:pos + n] = view
+ self._pos += n
return n
def seek(self, pos, whence=0):
diff --git a/contrib/tools/python3/Lib/_pyrepl/unix_console.py b/contrib/tools/python3/Lib/_pyrepl/unix_console.py
index 89ba7b38994..cf82721ed89 100644
--- a/contrib/tools/python3/Lib/_pyrepl/unix_console.py
+++ b/contrib/tools/python3/Lib/_pyrepl/unix_console.py
@@ -258,8 +258,9 @@ class UnixConsole(Console):
if not self.__gone_tall:
while len(self.screen) < min(len(screen), self.height):
self.__hide_cursor()
- self.__move(0, len(self.screen) - 1)
- self.__write("\n")
+ if self.screen:
+ self.__move(0, len(self.screen) - 1)
+ self.__write("\n")
self.posxy = 0, len(self.screen)
self.screen.append("")
else:
@@ -817,7 +818,7 @@ class UnixConsole(Console):
will never do anyone any good."""
# using .get() means that things will blow up
# only if the bps is actually needed (which I'm
- # betting is pretty unlkely)
+ # betting is pretty unlikely)
bps = ratedict.get(self.__svtermstate.ospeed)
while 1:
m = prog.search(fmt)
diff --git a/contrib/tools/python3/Lib/_pyrepl/windows_console.py b/contrib/tools/python3/Lib/_pyrepl/windows_console.py
index 05df4f6a19e..6d2a5cbb774 100644
--- a/contrib/tools/python3/Lib/_pyrepl/windows_console.py
+++ b/contrib/tools/python3/Lib/_pyrepl/windows_console.py
@@ -171,8 +171,9 @@ class WindowsConsole(Console):
while len(self.screen) < min(len(screen), self.height):
self._hide_cursor()
- self._move_relative(0, len(self.screen) - 1)
- self.__write("\n")
+ if self.screen:
+ self._move_relative(0, len(self.screen) - 1)
+ self.__write("\n")
self.posxy = 0, len(self.screen)
self.screen.append("")
@@ -498,7 +499,7 @@ class WindowsConsole(Console):
"""Wipe the screen"""
self.__write(CLEAR)
self.posxy = 0, 0
- self.screen = [""]
+ self.screen = []
def finish(self) -> None:
"""Move the cursor to the end of the display and otherwise get
@@ -526,7 +527,7 @@ class WindowsConsole(Console):
processed."""
return Event("key", "", b"")
- def wait(self, timeout: float | None) -> bool:
+ def wait_for_event(self, timeout: float | None) -> bool:
"""Wait for an event."""
# Poor man's Windows select loop
start_time = time.time()
@@ -537,6 +538,15 @@ class WindowsConsole(Console):
return False
time.sleep(0.01)
+ def wait(self, timeout: float | None) -> bool:
+ """
+ Wait for events on the console.
+ """
+ return (
+ not self.event_queue.empty()
+ or self.wait_for_event(timeout)
+ )
+
def repaint(self) -> None:
raise NotImplementedError("No repaint support")
diff --git a/contrib/tools/python3/Lib/_sitebuiltins.py b/contrib/tools/python3/Lib/_sitebuiltins.py
index c66269a5719..81b36efc6c2 100644
--- a/contrib/tools/python3/Lib/_sitebuiltins.py
+++ b/contrib/tools/python3/Lib/_sitebuiltins.py
@@ -36,7 +36,7 @@ class _Printer(object):
import os
self.__name = name
self.__data = data
- self.__lines = None
+ self.__lines = []
self.__filenames = [os.path.join(dir, filename)
for dir in dirs
for filename in files]
@@ -65,24 +65,12 @@ class _Printer(object):
return "Type %s() to see the full %s text" % ((self.__name,)*2)
def __call__(self):
+ from _pyrepl.pager import get_pager
self.__setup()
- prompt = 'Hit Return for more, or q (and Return) to quit: '
- lineno = 0
- while 1:
- try:
- for i in range(lineno, lineno + self.MAXLINES):
- print(self.__lines[i])
- except IndexError:
- break
- else:
- lineno += self.MAXLINES
- key = None
- while key is None:
- key = input(prompt)
- if key not in ('', 'q'):
- key = None
- if key == 'q':
- break
+
+ pager = get_pager()
+ text = "\n".join(self.__lines)
+ pager(text, title=self.__name)
class _Helper(object):
diff --git a/contrib/tools/python3/Lib/argparse.py b/contrib/tools/python3/Lib/argparse.py
index bd088ea0e66..a0faa3f41e2 100644
--- a/contrib/tools/python3/Lib/argparse.py
+++ b/contrib/tools/python3/Lib/argparse.py
@@ -330,8 +330,14 @@ class HelpFormatter(object):
if len(prefix) + len(usage) > text_width:
# break usage into wrappable parts
- opt_parts = self._get_actions_usage_parts(optionals, groups)
- pos_parts = self._get_actions_usage_parts(positionals, groups)
+ # keep optionals and positionals together to preserve
+ # mutually exclusive group formatting (gh-75949)
+ all_actions = optionals + positionals
+ parts, pos_start = self._get_actions_usage_parts_with_split(
+ all_actions, groups, len(optionals)
+ )
+ opt_parts = parts[:pos_start]
+ pos_parts = parts[pos_start:]
# helper for wrapping lines
def get_lines(parts, indent, prefix=None):
@@ -387,6 +393,17 @@ class HelpFormatter(object):
return ' '.join(self._get_actions_usage_parts(actions, groups))
def _get_actions_usage_parts(self, actions, groups):
+ parts, _ = self._get_actions_usage_parts_with_split(actions, groups)
+ return parts
+
+ def _get_actions_usage_parts_with_split(self, actions, groups, opt_count=None):
+ """Get usage parts with split index for optionals/positionals.
+
+ Returns (parts, pos_start) where pos_start is the index in parts
+ where positionals begin. When opt_count is None, pos_start is None.
+ This preserves mutually exclusive group formatting across the
+ optionals/positionals boundary (gh-75949).
+ """
# find group indices and identify actions in groups
group_actions = set()
inserts = {}
@@ -469,8 +486,16 @@ class HelpFormatter(object):
for i in range(start + group_size, end):
parts[i] = None
- # return the usage parts
- return [item for item in parts if item is not None]
+ # if opt_count is provided, calculate where positionals start in
+ # the final parts list (for wrapping onto separate lines).
+ # Count before filtering None entries since indices shift after.
+ if opt_count is not None:
+ pos_start = sum(1 for p in parts[:opt_count] if p is not None)
+ else:
+ pos_start = None
+
+ # return the usage parts and split point (gh-75949)
+ return [item for item in parts if item is not None], pos_start
def _format_text(self, text):
if '%(prog)' in text:
@@ -669,11 +694,14 @@ class ArgumentDefaultsHelpFormatter(HelpFormatter):
if help is None:
help = ''
- if '%(default)' not in help:
- if action.default is not SUPPRESS:
- defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
- if action.option_strings or action.nargs in defaulting_nargs:
- help += _(' (default: %(default)s)')
+ if (
+ '%(default)' not in help
+ and action.default is not SUPPRESS
+ and not action.required
+ ):
+ defaulting_nargs = (OPTIONAL, ZERO_OR_MORE)
+ if action.option_strings or action.nargs in defaulting_nargs:
+ help += _(' (default: %(default)s)')
return help
diff --git a/contrib/tools/python3/Lib/asyncio/__main__.py b/contrib/tools/python3/Lib/asyncio/__main__.py
index 8e9af83cc8a..42bfcdbf50f 100644
--- a/contrib/tools/python3/Lib/asyncio/__main__.py
+++ b/contrib/tools/python3/Lib/asyncio/__main__.py
@@ -84,16 +84,17 @@ class REPLThread(threading.Thread):
global return_code
try:
- banner = (
- f'asyncio REPL {sys.version} on {sys.platform}\n'
- f'Use "await" directly instead of "asyncio.run()".\n'
- f'Type "help", "copyright", "credits" or "license" '
- f'for more information.\n'
- )
+ if not sys.flags.quiet:
+ banner = (
+ f'asyncio REPL {sys.version} on {sys.platform}\n'
+ f'Use "await" directly instead of "asyncio.run()".\n'
+ f'Type "help", "copyright", "credits" or "license" '
+ f'for more information.\n'
+ )
- console.write(banner)
+ console.write(banner)
- if startup_path := os.getenv("PYTHONSTARTUP"):
+ if not sys.flags.isolated and (startup_path := os.getenv("PYTHONSTARTUP")):
sys.audit("cpython.run_startup", startup_path)
import tokenize
@@ -202,4 +203,5 @@ if __name__ == '__main__':
break
console.write('exiting asyncio REPL...\n')
+ loop.close()
sys.exit(return_code)
diff --git a/contrib/tools/python3/Lib/asyncio/futures.py b/contrib/tools/python3/Lib/asyncio/futures.py
index 51932639097..e24e16de751 100644
--- a/contrib/tools/python3/Lib/asyncio/futures.py
+++ b/contrib/tools/python3/Lib/asyncio/futures.py
@@ -383,7 +383,7 @@ def _chain_future(source, destination):
def _call_check_cancel(destination):
if destination.cancelled():
- if source_loop is None or source_loop is dest_loop:
+ if source_loop is None or source_loop is events._get_running_loop():
source.cancel()
else:
source_loop.call_soon_threadsafe(source.cancel)
@@ -392,7 +392,7 @@ def _chain_future(source, destination):
if (destination.cancelled() and
dest_loop is not None and dest_loop.is_closed()):
return
- if dest_loop is None or dest_loop is source_loop:
+ if dest_loop is None or dest_loop is events._get_running_loop():
_set_state(destination, source)
else:
if dest_loop.is_closed():
diff --git a/contrib/tools/python3/Lib/asyncio/selector_events.py b/contrib/tools/python3/Lib/asyncio/selector_events.py
index 8701467d413..ff7e16df3c6 100644
--- a/contrib/tools/python3/Lib/asyncio/selector_events.py
+++ b/contrib/tools/python3/Lib/asyncio/selector_events.py
@@ -173,16 +173,20 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
# listening socket has triggered an EVENT_READ. There may be multiple
# connections waiting for an .accept() so it is called in a loop.
# See https://bugs.python.org/issue27906 for more details.
- for _ in range(backlog):
+ for _ in range(backlog + 1):
try:
conn, addr = sock.accept()
if self._debug:
logger.debug("%r got a new connection from %r: %r",
server, addr, conn)
conn.setblocking(False)
- except (BlockingIOError, InterruptedError, ConnectionAbortedError):
- # Early exit because the socket accept buffer is empty.
- return None
+ except ConnectionAbortedError:
+ # Discard connections that were aborted before accept().
+ continue
+ except (BlockingIOError, InterruptedError):
+ # Early exit because of a signal or
+ # the socket accept buffer is empty.
+ return
except OSError as exc:
# There's nowhere to send the error, so just log it.
if exc.errno in (errno.EMFILE, errno.ENFILE,
diff --git a/contrib/tools/python3/Lib/email/_encoded_words.py b/contrib/tools/python3/Lib/email/_encoded_words.py
index 6795a606de0..05a34a4c105 100644
--- a/contrib/tools/python3/Lib/email/_encoded_words.py
+++ b/contrib/tools/python3/Lib/email/_encoded_words.py
@@ -219,7 +219,7 @@ def encode(string, charset='utf-8', encoding=None, lang=''):
"""
if charset == 'unknown-8bit':
- bstring = string.encode('ascii', 'surrogateescape')
+ bstring = string.encode('utf-8', 'surrogateescape')
else:
bstring = string.encode(charset)
if encoding is None:
diff --git a/contrib/tools/python3/Lib/email/_header_value_parser.py b/contrib/tools/python3/Lib/email/_header_value_parser.py
index 91243378dc0..51727688c05 100644
--- a/contrib/tools/python3/Lib/email/_header_value_parser.py
+++ b/contrib/tools/python3/Lib/email/_header_value_parser.py
@@ -101,6 +101,12 @@ def make_quoted_pairs(value):
return str(value).replace('\\', '\\\\').replace('"', '\\"')
+def make_parenthesis_pairs(value):
+ """Escape parenthesis and backslash for use within a comment."""
+ return str(value).replace('\\', '\\\\') \
+ .replace('(', '\\(').replace(')', '\\)')
+
+
def quote_string(value):
escaped = make_quoted_pairs(value)
return f'"{escaped}"'
@@ -874,6 +880,12 @@ class MessageID(MsgID):
class InvalidMessageID(MessageID):
token_type = 'invalid-message-id'
+class MessageIDList(TokenList):
+ token_type = 'message-id-list'
+
+ @property
+ def message_ids(self):
+ return [x for x in self if x.token_type=='msg-id']
class Header(TokenList):
token_type = 'header'
@@ -933,7 +945,7 @@ class WhiteSpaceTerminal(Terminal):
return ' '
def startswith_fws(self):
- return True
+ return self and self[0] in WSP
class ValueTerminal(Terminal):
@@ -2171,6 +2183,32 @@ def parse_message_id(value):
return message_id
+def parse_message_ids(value):
+ """in-reply-to = "In-Reply-To:" 1*msg-id CRLF
+ references = "References:" 1*msg-id CRLF
+ """
+ message_id_list = MessageIDList()
+ while value:
+ if value[0] == ',':
+ # message id list separated with commas - this is invalid,
+ # but happens rather frequently in the wild
+ message_id_list.defects.append(
+ errors.InvalidHeaderDefect("comma in msg-id list"))
+ message_id_list.append(
+ WhiteSpaceTerminal(' ', 'invalid-comma-replacement'))
+ value = value[1:]
+ continue
+ try:
+ token, value = get_msg_id(value)
+ message_id_list.append(token)
+ except errors.HeaderParseError as ex:
+ token = get_unstructured(value)
+ message_id_list.append(InvalidMessageID(token))
+ message_id_list.defects.append(
+ errors.InvalidHeaderDefect("Invalid msg-id: {!r}".format(ex)))
+ break
+ return message_id_list
+
#
# XXX: As I begin to add additional header parsers, I'm realizing we probably
# have two level of parser routines: the get_XXX methods that get a token in
@@ -2788,6 +2826,9 @@ def _steal_trailing_WSP_if_exists(lines):
if lines and lines[-1] and lines[-1][-1] in WSP:
wsp = lines[-1][-1]
lines[-1] = lines[-1][:-1]
+ # gh-142006: if the line is now empty, remove it entirely.
+ if not lines[-1]:
+ lines.pop()
return wsp
def _refold_parse_tree(parse_tree, *, policy):
@@ -2924,6 +2965,13 @@ def _refold_parse_tree(parse_tree, *, policy):
[ValueTerminal(make_quoted_pairs(p), 'ptext')
for p in newparts] +
[ValueTerminal('"', 'ptext')])
+ if part.token_type == 'comment':
+ newparts = (
+ [ValueTerminal('(', 'ptext')] +
+ [ValueTerminal(make_parenthesis_pairs(p), 'ptext')
+ if p.token_type == 'ptext' else p
+ for p in newparts] +
+ [ValueTerminal(')', 'ptext')])
if not part.as_ew_allowed:
wrap_as_ew_blocked += 1
newparts.append(end_ew_not_allowed)
diff --git a/contrib/tools/python3/Lib/email/feedparser.py b/contrib/tools/python3/Lib/email/feedparser.py
index bc773f38030..8e60f1d1181 100644
--- a/contrib/tools/python3/Lib/email/feedparser.py
+++ b/contrib/tools/python3/Lib/email/feedparser.py
@@ -504,10 +504,9 @@ class FeedParser:
self._input.unreadline(line)
return
else:
- # Weirdly placed unix-from line. Note this as a defect
- # and ignore it.
+ # Weirdly placed unix-from line.
defect = errors.MisplacedEnvelopeHeaderDefect(line)
- self._cur.defects.append(defect)
+ self.policy.handle_defect(self._cur, defect)
continue
# Split the line on the colon separating field name from value.
# There will always be a colon, because if there wasn't the part of
@@ -519,7 +518,7 @@ class FeedParser:
# message. Track the error but keep going.
if i == 0:
defect = errors.InvalidHeaderDefect("Missing header name.")
- self._cur.defects.append(defect)
+ self.policy.handle_defect(self._cur, defect)
continue
assert i>0, "_parse_headers fed line with no : and no leading WS"
diff --git a/contrib/tools/python3/Lib/email/generator.py b/contrib/tools/python3/Lib/email/generator.py
index ce94f5c56fe..a03eb1fbbc9 100644
--- a/contrib/tools/python3/Lib/email/generator.py
+++ b/contrib/tools/python3/Lib/email/generator.py
@@ -22,6 +22,7 @@ NL = '\n' # XXX: no longer used by the code below.
NLCRE = re.compile(r'\r\n|\r|\n')
fcre = re.compile(r'^From ', re.MULTILINE)
NEWLINE_WITHOUT_FWSP = re.compile(r'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
+NEWLINE_WITHOUT_FWSP_BYTES = re.compile(br'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
class Generator:
@@ -429,7 +430,16 @@ class BytesGenerator(Generator):
# This is almost the same as the string version, except for handling
# strings with 8bit bytes.
for h, v in msg.raw_items():
- self._fp.write(self.policy.fold_binary(h, v))
+ folded = self.policy.fold_binary(h, v)
+ if self.policy.verify_generated_headers:
+ linesep = self.policy.linesep.encode()
+ if not folded.endswith(linesep):
+ raise HeaderWriteError(
+ f'folded header does not end with {linesep!r}: {folded!r}')
+ if NEWLINE_WITHOUT_FWSP_BYTES.search(folded.removesuffix(linesep)):
+ raise HeaderWriteError(
+ f'folded header contains newline: {folded!r}')
+ self._fp.write(folded)
# A blank line always separates headers from body
self.write(self._NL)
diff --git a/contrib/tools/python3/Lib/email/headerregistry.py b/contrib/tools/python3/Lib/email/headerregistry.py
index 543141dc427..0e8698efc0b 100644
--- a/contrib/tools/python3/Lib/email/headerregistry.py
+++ b/contrib/tools/python3/Lib/email/headerregistry.py
@@ -534,6 +534,18 @@ class MessageIDHeader:
kwds['defects'].extend(parse_tree.all_defects)
+class ReferencesHeader:
+
+ max_count = 1
+ value_parser = staticmethod(parser.parse_message_ids)
+
+ @classmethod
+ def parse(cls, value, kwds):
+ kwds['parse_tree'] = parse_tree = cls.value_parser(value)
+ kwds['decoded'] = str(parse_tree)
+ kwds['defects'].extend(parse_tree.all_defects)
+
+
# The header factory #
_default_header_map = {
@@ -557,6 +569,8 @@ _default_header_map = {
'content-disposition': ContentDispositionHeader,
'content-transfer-encoding': ContentTransferEncodingHeader,
'message-id': MessageIDHeader,
+ 'in-reply-to': ReferencesHeader,
+ 'references': ReferencesHeader,
}
class HeaderRegistry:
diff --git a/contrib/tools/python3/Lib/enum.py b/contrib/tools/python3/Lib/enum.py
index 51074404af3..5e7b00654dd 100644
--- a/contrib/tools/python3/Lib/enum.py
+++ b/contrib/tools/python3/Lib/enum.py
@@ -130,7 +130,7 @@ def show_flag_values(value):
def bin(num, max_bits=None):
"""
Like built-in bin(), except negative values are represented in
- twos-compliment, and the leading bit always indicates sign
+ twos-complement, and the leading bit always indicates sign
(0=positive, 1=negative).
>>> bin(10)
@@ -139,6 +139,7 @@ def bin(num, max_bits=None):
'0b1 0101'
"""
+ num = num.__index__()
ceiling = 2 ** (num).bit_length()
if num >= 0:
s = bltns.bin(num + ceiling).replace('1', '0', 1)
diff --git a/contrib/tools/python3/Lib/hmac.py b/contrib/tools/python3/Lib/hmac.py
index 8b4eb2fe741..a49f2aeb1d6 100644
--- a/contrib/tools/python3/Lib/hmac.py
+++ b/contrib/tools/python3/Lib/hmac.py
@@ -127,6 +127,7 @@ class HMAC:
# Call __new__ directly to avoid the expensive __init__.
other = self.__class__.__new__(self.__class__)
other.digest_size = self.digest_size
+ other.block_size = self.block_size
if self._hmac:
other._hmac = self._hmac.copy()
other._inner = other._outer = None
diff --git a/contrib/tools/python3/Lib/http/cookies.py b/contrib/tools/python3/Lib/http/cookies.py
index 57791c6ab08..d0a69cbe191 100644
--- a/contrib/tools/python3/Lib/http/cookies.py
+++ b/contrib/tools/python3/Lib/http/cookies.py
@@ -87,9 +87,9 @@ within a string. Escaped quotation marks, nested semicolons, and other
such trickeries do not confuse it.
>>> C = cookies.SimpleCookie()
- >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
+ >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=;";')
>>> print(C)
- Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
+ Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=;"
Each element of the Cookie also supports all of the RFC 2109
Cookie attributes. Here's an example which sets the Path
@@ -170,6 +170,15 @@ _Translator.update({
})
_is_legal_key = re.compile('[%s]+' % re.escape(_LegalChars)).fullmatch
+_control_character_re = re.compile(r'[\x00-\x1F\x7F]')
+
+
+def _has_control_character(*val):
+ """Detects control characters within a value.
+ Supports any type, as header values can be any type.
+ """
+ return any(_control_character_re.search(str(v)) for v in val)
+
def _quote(str):
r"""Quote a string for use in a cookie header.
@@ -292,12 +301,16 @@ class Morsel(dict):
K = K.lower()
if not K in self._reserved:
raise CookieError("Invalid attribute %r" % (K,))
+ if _has_control_character(K, V):
+ raise CookieError(f"Control characters are not allowed in cookies {K!r} {V!r}")
dict.__setitem__(self, K, V)
def setdefault(self, key, val=None):
key = key.lower()
if key not in self._reserved:
raise CookieError("Invalid attribute %r" % (key,))
+ if _has_control_character(key, val):
+ raise CookieError("Control characters are not allowed in cookies %r %r" % (key, val,))
return dict.setdefault(self, key, val)
def __eq__(self, morsel):
@@ -333,6 +346,9 @@ class Morsel(dict):
raise CookieError('Attempt to set a reserved key %r' % (key,))
if not _is_legal_key(key):
raise CookieError('Illegal key %r' % (key,))
+ if _has_control_character(key, val, coded_val):
+ raise CookieError(
+ "Control characters are not allowed in cookies %r %r %r" % (key, val, coded_val,))
# It's a good key, so save it.
self._key = key
@@ -486,7 +502,10 @@ class BaseCookie(dict):
result = []
items = sorted(self.items())
for key, value in items:
- result.append(value.output(attrs, header))
+ value_output = value.output(attrs, header)
+ if _has_control_character(value_output):
+ raise CookieError("Control characters are not allowed in cookies")
+ result.append(value_output)
return sep.join(result)
__str__ = output
diff --git a/contrib/tools/python3/Lib/inspect.py b/contrib/tools/python3/Lib/inspect.py
index 5a814f97b5b..cee6a7f1833 100644
--- a/contrib/tools/python3/Lib/inspect.py
+++ b/contrib/tools/python3/Lib/inspect.py
@@ -465,6 +465,8 @@ def isgenerator(object):
gi_frame frame object or possibly None once the generator has
been exhausted
gi_running set to 1 when generator is executing, 0 otherwise
+ gi_suspended set to 1 when the generator is suspended at a yield point, 0 otherwise
+ gi_yieldfrom object being iterated by yield from or None
next return the next item from the container
send resumes the generator and "sends" a value that becomes
the result of the current yield-expression
diff --git a/contrib/tools/python3/Lib/linecache.py b/contrib/tools/python3/Lib/linecache.py
index 7d257e34460..0868d20d523 100644
--- a/contrib/tools/python3/Lib/linecache.py
+++ b/contrib/tools/python3/Lib/linecache.py
@@ -33,10 +33,9 @@ def getlines(filename, module_globals=None):
"""Get the lines for a Python source file from the cache.
Update the cache if it doesn't contain an entry for this file already."""
- if filename in cache:
- entry = cache[filename]
- if len(entry) != 1:
- return cache[filename][2]
+ entry = cache.get(filename, None)
+ if entry is not None and len(entry) != 1:
+ return entry[2]
try:
return updatecache(filename, module_globals)
@@ -56,10 +55,9 @@ def _make_key(code):
def _getlines_from_code(code):
code_id = _make_key(code)
- if code_id in _interactive_cache:
- entry = _interactive_cache[code_id]
- if len(entry) != 1:
- return _interactive_cache[code_id][2]
+ entry = _interactive_cache.get(code_id, None)
+ if entry is not None and len(entry) != 1:
+ return entry[2]
return []
@@ -74,12 +72,8 @@ def checkcache(filename=None):
filenames = [filename]
for filename in filenames:
- try:
- entry = cache[filename]
- except KeyError:
- continue
-
- if len(entry) == 1:
+ entry = cache.get(filename, None)
+ if entry is None or len(entry) == 1:
# lazy cache entry, leave it lazy.
continue
size, mtime, lines, fullname = entry
@@ -116,9 +110,7 @@ def updatecache(filename, module_globals=None):
# These import can fail if the interpreter is shutting down
return []
- if filename in cache:
- if len(cache[filename]) != 1:
- cache.pop(filename, None)
+ entry = cache.pop(filename, None)
if not filename or (filename.startswith('<') and filename.endswith('>')):
return []
@@ -136,9 +128,12 @@ def updatecache(filename, module_globals=None):
# Realise a lazy loader based lookup if there is one
# otherwise try to lookup right now.
- if lazycache(filename, module_globals):
+ lazy_entry = entry if entry is not None and len(entry) == 1 else None
+ if lazy_entry is None:
+ lazy_entry = _make_lazycache_entry(filename, module_globals)
+ if lazy_entry is not None:
try:
- data = cache[filename][0]()
+ data = lazy_entry[0]()
except (ImportError, OSError):
pass
else:
@@ -146,13 +141,14 @@ def updatecache(filename, module_globals=None):
# No luck, the PEP302 loader cannot find the source
# for this module.
return []
- cache[filename] = (
+ entry = (
len(data),
None,
[line + '\n' for line in data.splitlines()],
fullname
)
- return cache[filename][2]
+ cache[filename] = entry
+ return entry[2]
# Try looking through the module search path, which is only useful
# when handling a relative filename.
@@ -201,13 +197,20 @@ def lazycache(filename, module_globals):
get_source method must be found, the filename must be a cacheable
filename, and the filename must not be already cached.
"""
- if filename in cache:
- if len(cache[filename]) == 1:
- return True
- else:
- return False
+ entry = cache.get(filename, None)
+ if entry is not None:
+ return len(entry) == 1
+
+ lazy_entry = _make_lazycache_entry(filename, module_globals)
+ if lazy_entry is not None:
+ cache[filename] = lazy_entry
+ return True
+ return False
+
+
+def _make_lazycache_entry(filename, module_globals):
if not filename or (filename.startswith('<') and filename.endswith('>')):
- return False
+ return None
# Try for a __loader__, if available
if module_globals and '__name__' in module_globals:
spec = module_globals.get('__spec__')
@@ -220,9 +223,10 @@ def lazycache(filename, module_globals):
if name and get_source:
def get_lines(name=name, *args, **kwargs):
return get_source(name, *args, **kwargs)
- cache[filename] = (get_lines,)
- return True
- return False
+ return (get_lines,)
+ return None
+
+
def _register_code(code, string, name):
entry = (len(string),
@@ -235,4 +239,5 @@ def _register_code(code, string, name):
for const in code.co_consts:
if isinstance(const, type(code)):
stack.append(const)
- _interactive_cache[_make_key(code)] = entry
+ key = _make_key(code)
+ _interactive_cache[key] = entry
diff --git a/contrib/tools/python3/Lib/logging/handlers.py b/contrib/tools/python3/Lib/logging/handlers.py
index d3ea06c731e..480dbd08e00 100644
--- a/contrib/tools/python3/Lib/logging/handlers.py
+++ b/contrib/tools/python3/Lib/logging/handlers.py
@@ -196,7 +196,11 @@ class RotatingFileHandler(BaseRotatingHandler):
if self.stream is None: # delay was set...
self.stream = self._open()
if self.maxBytes > 0: # are we rolling over?
- pos = self.stream.tell()
+ try:
+ pos = self.stream.tell()
+ except io.UnsupportedOperation:
+ # gh-143237: Never rollover a named pipe.
+ return False
if not pos:
# gh-116263: Never rollover an empty file
return False
diff --git a/contrib/tools/python3/Lib/mailbox.py b/contrib/tools/python3/Lib/mailbox.py
index b00d9e8634c..364af6bb010 100644
--- a/contrib/tools/python3/Lib/mailbox.py
+++ b/contrib/tools/python3/Lib/mailbox.py
@@ -2183,11 +2183,7 @@ def _unlock_file(f):
def _create_carefully(path):
"""Create a file if it doesn't exist and open for reading and writing."""
- fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0o666)
- try:
- return open(path, 'rb+')
- finally:
- os.close(fd)
+ return open(path, 'xb+')
def _create_temporary(path):
"""Create a temp file based on path and open for reading and writing."""
diff --git a/contrib/tools/python3/Lib/multiprocessing/forkserver.py b/contrib/tools/python3/Lib/multiprocessing/forkserver.py
index e243442e7a1..009da9b40bb 100644
--- a/contrib/tools/python3/Lib/multiprocessing/forkserver.py
+++ b/contrib/tools/python3/Lib/multiprocessing/forkserver.py
@@ -134,6 +134,8 @@ class ForkServer(object):
main_kws['sys_path'] = data['sys_path']
if 'init_main_from_path' in data:
main_kws['main_path'] = data['init_main_from_path']
+ if 'sys_argv' in data:
+ main_kws['sys_argv'] = data['sys_argv']
with socket.socket(socket.AF_UNIX) as listener:
address = connection.arbitrary_address('AF_UNIX')
@@ -166,9 +168,12 @@ class ForkServer(object):
#
#
-def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
+def main(listener_fd, alive_r, preload, main_path=None, sys_path=None,
+ *, sys_argv=None):
'''Run forkserver.'''
if preload:
+ if sys_argv is not None:
+ sys.argv[:] = sys_argv
if sys_path is not None:
sys.path[:] = sys_path
if '__main__' in preload and main_path is not None:
diff --git a/contrib/tools/python3/Lib/multiprocessing/spawn.py b/contrib/tools/python3/Lib/multiprocessing/spawn.py
index a0ab98cfd2c..1af00df7bc7 100644
--- a/contrib/tools/python3/Lib/multiprocessing/spawn.py
+++ b/contrib/tools/python3/Lib/multiprocessing/spawn.py
@@ -184,7 +184,7 @@ def get_preparation_data(name):
sys_argv=sys.argv,
orig_dir=process.ORIGINAL_DIR,
dir=os.getcwd(),
- start_method=get_start_method(),
+ start_method=get_start_method(allow_none=True),
)
# Figure out whether to initialise main in the subprocess as a module
diff --git a/contrib/tools/python3/Lib/pdb.py b/contrib/tools/python3/Lib/pdb.py
index 063b12cc856..5c9be23e326 100755
--- a/contrib/tools/python3/Lib/pdb.py
+++ b/contrib/tools/python3/Lib/pdb.py
@@ -172,19 +172,37 @@ class _ExecutableTarget:
class _ScriptTarget(_ExecutableTarget):
def __init__(self, target):
- self._target = os.path.realpath(target)
+ self._check(target)
+ self._target = self._safe_realpath(target)
- if not os.path.exists(self._target):
+ # If PYTHONSAFEPATH (-P) is not set, sys.path[0] is the directory
+ # of pdb, and we should replace it with the directory of the script
+ if not sys.flags.safe_path:
+ sys.path[0] = os.path.dirname(self._target)
+
+ @staticmethod
+ def _check(target):
+ """
+ Check that target is plausibly a script.
+ """
+ if not os.path.exists(target):
print(f'Error: {target} does not exist')
sys.exit(1)
- if os.path.isdir(self._target):
+ if os.path.isdir(target):
print(f'Error: {target} is a directory')
sys.exit(1)
- # If safe_path(-P) is not set, sys.path[0] is the directory
- # of pdb, and we should replace it with the directory of the script
- if not sys.flags.safe_path:
- sys.path[0] = os.path.dirname(self._target)
+ @staticmethod
+ def _safe_realpath(path):
+ """
+ Return the canonical path (realpath) if it is accessible from the userspace.
+ Otherwise (for example, if the path is a symlink to an anonymous pipe),
+ return the original path.
+
+ See GH-142315.
+ """
+ realpath = os.path.realpath(path)
+ return realpath if os.path.exists(realpath) else path
def __repr__(self):
return self._target
diff --git a/contrib/tools/python3/Lib/plistlib.py b/contrib/tools/python3/Lib/plistlib.py
index 655c51eea3d..5b2b4e42c95 100644
--- a/contrib/tools/python3/Lib/plistlib.py
+++ b/contrib/tools/python3/Lib/plistlib.py
@@ -384,7 +384,7 @@ class _PlistWriter(_DumbXMLWriter):
self._indent_level -= 1
maxlinelength = max(
16,
- 76 - len(self.indent.replace(b"\t", b" " * 8) * self._indent_level))
+ 76 - len((self.indent * self._indent_level).expandtabs()))
for line in _encode_base64(data, maxlinelength).split(b"\n"):
if line:
diff --git a/contrib/tools/python3/Lib/pydoc.py b/contrib/tools/python3/Lib/pydoc.py
index 94ada32f3d8..d5b56f7ee08 100755
--- a/contrib/tools/python3/Lib/pydoc.py
+++ b/contrib/tools/python3/Lib/pydoc.py
@@ -574,10 +574,20 @@ class Doc:
(file.startswith(basedir) and
not file.startswith(os.path.join(basedir, 'site-packages')))) and
object.__name__ not in ('xml.etree', 'test.test_pydoc.pydoc_mod')):
- if docloc.startswith(("http://", "https://")):
- docloc = "{}/{}.html".format(docloc.rstrip("/"), object.__name__.lower())
+
+ try:
+ from pydoc_data import module_docs
+ except ImportError:
+ module_docs = None
+
+ if module_docs and object.__name__ in module_docs.module_docs:
+ doc_name = module_docs.module_docs[object.__name__]
+ if docloc.startswith(("http://", "https://")):
+ docloc = "{}/{}".format(docloc.rstrip("/"), doc_name)
+ else:
+ docloc = os.path.join(docloc, doc_name)
else:
- docloc = os.path.join(docloc, object.__name__.lower() + ".html")
+ docloc = None
else:
docloc = None
return docloc
@@ -2018,10 +2028,11 @@ has the same effect as typing a particular string at the help> prompt.
while True:
try:
request = self.getline('help> ')
- if not request: break
except (KeyboardInterrupt, EOFError):
break
request = request.strip()
+ if not request:
+ continue # back to the prompt
# Make sure significant trailing quoting marks of literals don't
# get deleted while cleaning input
diff --git a/contrib/tools/python3/Lib/pydoc_data/module_docs.py b/contrib/tools/python3/Lib/pydoc_data/module_docs.py
new file mode 100644
index 00000000000..39ffd714145
--- /dev/null
+++ b/contrib/tools/python3/Lib/pydoc_data/module_docs.py
@@ -0,0 +1,314 @@
+# Autogenerated by Sphinx on Tue Feb 3 18:53:22 2026
+# as part of the release process.
+
+module_docs = {
+ '__future__': '__future__#module-__future__',
+ '__main__': '__main__#module-__main__',
+ '_thread': '_thread#module-_thread',
+ '_tkinter': 'tkinter#module-_tkinter',
+ 'abc': 'abc#module-abc',
+ 'aifc': 'aifc#module-aifc',
+ 'argparse': 'argparse#module-argparse',
+ 'array': 'array#module-array',
+ 'ast': 'ast#module-ast',
+ 'asynchat': 'asynchat#module-asynchat',
+ 'asyncio': 'asyncio#module-asyncio',
+ 'asyncore': 'asyncore#module-asyncore',
+ 'atexit': 'atexit#module-atexit',
+ 'audioop': 'audioop#module-audioop',
+ 'base64': 'base64#module-base64',
+ 'bdb': 'bdb#module-bdb',
+ 'binascii': 'binascii#module-binascii',
+ 'bisect': 'bisect#module-bisect',
+ 'builtins': 'builtins#module-builtins',
+ 'bz2': 'bz2#module-bz2',
+ 'cProfile': 'profile#module-cProfile',
+ 'calendar': 'calendar#module-calendar',
+ 'cgi': 'cgi#module-cgi',
+ 'cgitb': 'cgitb#module-cgitb',
+ 'chunk': 'chunk#module-chunk',
+ 'cmath': 'cmath#module-cmath',
+ 'cmd': 'cmd#module-cmd',
+ 'code': 'code#module-code',
+ 'codecs': 'codecs#module-codecs',
+ 'codeop': 'codeop#module-codeop',
+ 'collections': 'collections#module-collections',
+ 'collections.abc': 'collections.abc#module-collections.abc',
+ 'colorsys': 'colorsys#module-colorsys',
+ 'compileall': 'compileall#module-compileall',
+ 'concurrent.futures': 'concurrent.futures#module-concurrent.futures',
+ 'configparser': 'configparser#module-configparser',
+ 'contextlib': 'contextlib#module-contextlib',
+ 'contextvars': 'contextvars#module-contextvars',
+ 'copy': 'copy#module-copy',
+ 'copyreg': 'copyreg#module-copyreg',
+ 'crypt': 'crypt#module-crypt',
+ 'csv': 'csv#module-csv',
+ 'ctypes': 'ctypes#module-ctypes',
+ 'curses': 'curses#module-curses',
+ 'curses.ascii': 'curses.ascii#module-curses.ascii',
+ 'curses.panel': 'curses.panel#module-curses.panel',
+ 'curses.textpad': 'curses#module-curses.textpad',
+ 'dataclasses': 'dataclasses#module-dataclasses',
+ 'datetime': 'datetime#module-datetime',
+ 'dbm': 'dbm#module-dbm',
+ 'dbm.dumb': 'dbm#module-dbm.dumb',
+ 'dbm.gnu': 'dbm#module-dbm.gnu',
+ 'dbm.ndbm': 'dbm#module-dbm.ndbm',
+ 'dbm.sqlite3': 'dbm#module-dbm.sqlite3',
+ 'decimal': 'decimal#module-decimal',
+ 'difflib': 'difflib#module-difflib',
+ 'dis': 'dis#module-dis',
+ 'distutils': 'distutils#module-distutils',
+ 'doctest': 'doctest#module-doctest',
+ 'email': 'email#module-email',
+ 'email.charset': 'email.charset#module-email.charset',
+ 'email.contentmanager': 'email.contentmanager#module-email.contentmanager',
+ 'email.encoders': 'email.encoders#module-email.encoders',
+ 'email.errors': 'email.errors#module-email.errors',
+ 'email.generator': 'email.generator#module-email.generator',
+ 'email.header': 'email.header#module-email.header',
+ 'email.headerregistry': 'email.headerregistry#module-email.headerregistry',
+ 'email.iterators': 'email.iterators#module-email.iterators',
+ 'email.message': 'email.message#module-email.message',
+ 'email.mime': 'email.mime#module-email.mime',
+ 'email.mime.application': 'email.mime#module-email.mime.application',
+ 'email.mime.audio': 'email.mime#module-email.mime.audio',
+ 'email.mime.base': 'email.mime#module-email.mime.base',
+ 'email.mime.image': 'email.mime#module-email.mime.image',
+ 'email.mime.message': 'email.mime#module-email.mime.message',
+ 'email.mime.multipart': 'email.mime#module-email.mime.multipart',
+ 'email.mime.nonmultipart': 'email.mime#module-email.mime.nonmultipart',
+ 'email.mime.text': 'email.mime#module-email.mime.text',
+ 'email.parser': 'email.parser#module-email.parser',
+ 'email.policy': 'email.policy#module-email.policy',
+ 'email.utils': 'email.utils#module-email.utils',
+ 'encodings': 'codecs#module-encodings',
+ 'encodings.idna': 'codecs#module-encodings.idna',
+ 'encodings.mbcs': 'codecs#module-encodings.mbcs',
+ 'encodings.utf_8_sig': 'codecs#module-encodings.utf_8_sig',
+ 'ensurepip': 'ensurepip#module-ensurepip',
+ 'enum': 'enum#module-enum',
+ 'errno': 'errno#module-errno',
+ 'faulthandler': 'faulthandler#module-faulthandler',
+ 'fcntl': 'fcntl#module-fcntl',
+ 'filecmp': 'filecmp#module-filecmp',
+ 'fileinput': 'fileinput#module-fileinput',
+ 'fnmatch': 'fnmatch#module-fnmatch',
+ 'fractions': 'fractions#module-fractions',
+ 'ftplib': 'ftplib#module-ftplib',
+ 'functools': 'functools#module-functools',
+ 'gc': 'gc#module-gc',
+ 'getopt': 'getopt#module-getopt',
+ 'getpass': 'getpass#module-getpass',
+ 'gettext': 'gettext#module-gettext',
+ 'glob': 'glob#module-glob',
+ 'graphlib': 'graphlib#module-graphlib',
+ 'grp': 'grp#module-grp',
+ 'gzip': 'gzip#module-gzip',
+ 'hashlib': 'hashlib#module-hashlib',
+ 'heapq': 'heapq#module-heapq',
+ 'hmac': 'hmac#module-hmac',
+ 'html': 'html#module-html',
+ 'html.entities': 'html.entities#module-html.entities',
+ 'html.parser': 'html.parser#module-html.parser',
+ 'http': 'http#module-http',
+ 'http.client': 'http.client#module-http.client',
+ 'http.cookiejar': 'http.cookiejar#module-http.cookiejar',
+ 'http.cookies': 'http.cookies#module-http.cookies',
+ 'http.server': 'http.server#module-http.server',
+ 'idlelib': 'idle#module-idlelib',
+ 'imaplib': 'imaplib#module-imaplib',
+ 'imghdr': 'imghdr#module-imghdr',
+ 'imp': 'imp#module-imp',
+ 'importlib': 'importlib#module-importlib',
+ 'importlib.abc': 'importlib#module-importlib.abc',
+ 'importlib.machinery': 'importlib#module-importlib.machinery',
+ 'importlib.metadata': 'importlib.metadata#module-importlib.metadata',
+ 'importlib.resources': 'importlib.resources#module-importlib.resources',
+ 'importlib.resources.abc': 'importlib.resources.abc#module-importlib.resources.abc',
+ 'importlib.util': 'importlib#module-importlib.util',
+ 'inspect': 'inspect#module-inspect',
+ 'io': 'io#module-io',
+ 'ipaddress': 'ipaddress#module-ipaddress',
+ 'itertools': 'itertools#module-itertools',
+ 'json': 'json#module-json',
+ 'json.tool': 'json#module-json.tool',
+ 'keyword': 'keyword#module-keyword',
+ 'linecache': 'linecache#module-linecache',
+ 'locale': 'locale#module-locale',
+ 'logging': 'logging#module-logging',
+ 'logging.config': 'logging.config#module-logging.config',
+ 'logging.handlers': 'logging.handlers#module-logging.handlers',
+ 'lzma': 'lzma#module-lzma',
+ 'mailbox': 'mailbox#module-mailbox',
+ 'mailcap': 'mailcap#module-mailcap',
+ 'marshal': 'marshal#module-marshal',
+ 'math': 'math#module-math',
+ 'mimetypes': 'mimetypes#module-mimetypes',
+ 'mmap': 'mmap#module-mmap',
+ 'modulefinder': 'modulefinder#module-modulefinder',
+ 'msilib': 'msilib#module-msilib',
+ 'msvcrt': 'msvcrt#module-msvcrt',
+ 'multiprocessing': 'multiprocessing#module-multiprocessing',
+ 'multiprocessing.connection': 'multiprocessing#module-multiprocessing.connection',
+ 'multiprocessing.dummy': 'multiprocessing#module-multiprocessing.dummy',
+ 'multiprocessing.managers': 'multiprocessing#module-multiprocessing.managers',
+ 'multiprocessing.pool': 'multiprocessing#module-multiprocessing.pool',
+ 'multiprocessing.shared_memory': 'multiprocessing.shared_memory#module-multiprocessing.shared_memory',
+ 'multiprocessing.sharedctypes': 'multiprocessing#module-multiprocessing.sharedctypes',
+ 'netrc': 'netrc#module-netrc',
+ 'nis': 'nis#module-nis',
+ 'nntplib': 'nntplib#module-nntplib',
+ 'numbers': 'numbers#module-numbers',
+ 'operator': 'operator#module-operator',
+ 'optparse': 'optparse#module-optparse',
+ 'os': 'os#module-os',
+ 'os.path': 'os.path#module-os.path',
+ 'ossaudiodev': 'ossaudiodev#module-ossaudiodev',
+ 'pathlib': 'pathlib#module-pathlib',
+ 'pdb': 'pdb#module-pdb',
+ 'pickle': 'pickle#module-pickle',
+ 'pickletools': 'pickletools#module-pickletools',
+ 'pipes': 'pipes#module-pipes',
+ 'pkgutil': 'pkgutil#module-pkgutil',
+ 'platform': 'platform#module-platform',
+ 'plistlib': 'plistlib#module-plistlib',
+ 'poplib': 'poplib#module-poplib',
+ 'posix': 'posix#module-posix',
+ 'pprint': 'pprint#module-pprint',
+ 'profile': 'profile#module-profile',
+ 'pstats': 'profile#module-pstats',
+ 'pty': 'pty#module-pty',
+ 'pwd': 'pwd#module-pwd',
+ 'py_compile': 'py_compile#module-py_compile',
+ 'pyclbr': 'pyclbr#module-pyclbr',
+ 'pydoc': 'pydoc#module-pydoc',
+ 'queue': 'queue#module-queue',
+ 'quopri': 'quopri#module-quopri',
+ 'random': 'random#module-random',
+ 're': 're#module-re',
+ 'readline': 'readline#module-readline',
+ 'reprlib': 'reprlib#module-reprlib',
+ 'resource': 'resource#module-resource',
+ 'rlcompleter': 'rlcompleter#module-rlcompleter',
+ 'runpy': 'runpy#module-runpy',
+ 'sched': 'sched#module-sched',
+ 'secrets': 'secrets#module-secrets',
+ 'select': 'select#module-select',
+ 'selectors': 'selectors#module-selectors',
+ 'shelve': 'shelve#module-shelve',
+ 'shlex': 'shlex#module-shlex',
+ 'shutil': 'shutil#module-shutil',
+ 'signal': 'signal#module-signal',
+ 'site': 'site#module-site',
+ 'sitecustomize': 'site#module-sitecustomize',
+ 'smtpd': 'smtpd#module-smtpd',
+ 'smtplib': 'smtplib#module-smtplib',
+ 'sndhdr': 'sndhdr#module-sndhdr',
+ 'socket': 'socket#module-socket',
+ 'socketserver': 'socketserver#module-socketserver',
+ 'spwd': 'spwd#module-spwd',
+ 'sqlite3': 'sqlite3#module-sqlite3',
+ 'ssl': 'ssl#module-ssl',
+ 'stat': 'stat#module-stat',
+ 'statistics': 'statistics#module-statistics',
+ 'string': 'string#module-string',
+ 'stringprep': 'stringprep#module-stringprep',
+ 'struct': 'struct#module-struct',
+ 'subprocess': 'subprocess#module-subprocess',
+ 'sunau': 'sunau#module-sunau',
+ 'symtable': 'symtable#module-symtable',
+ 'sys': 'sys#module-sys',
+ 'sys.monitoring': 'sys.monitoring#module-sys.monitoring',
+ 'sysconfig': 'sysconfig#module-sysconfig',
+ 'syslog': 'syslog#module-syslog',
+ 'tabnanny': 'tabnanny#module-tabnanny',
+ 'tarfile': 'tarfile#module-tarfile',
+ 'telnetlib': 'telnetlib#module-telnetlib',
+ 'tempfile': 'tempfile#module-tempfile',
+ 'termios': 'termios#module-termios',
+ 'test': 'test#module-test',
+ 'test.regrtest': 'test#module-test.regrtest',
+ 'test.support': 'test#module-test.support',
+ 'test.support.bytecode_helper': 'test#module-test.support.bytecode_helper',
+ 'test.support.import_helper': 'test#module-test.support.import_helper',
+ 'test.support.os_helper': 'test#module-test.support.os_helper',
+ 'test.support.script_helper': 'test#module-test.support.script_helper',
+ 'test.support.socket_helper': 'test#module-test.support.socket_helper',
+ 'test.support.threading_helper': 'test#module-test.support.threading_helper',
+ 'test.support.warnings_helper': 'test#module-test.support.warnings_helper',
+ 'textwrap': 'textwrap#module-textwrap',
+ 'threading': 'threading#module-threading',
+ 'time': 'time#module-time',
+ 'timeit': 'timeit#module-timeit',
+ 'tkinter': 'tkinter#module-tkinter',
+ 'tkinter.colorchooser': 'tkinter.colorchooser#module-tkinter.colorchooser',
+ 'tkinter.commondialog': 'dialog#module-tkinter.commondialog',
+ 'tkinter.dnd': 'tkinter.dnd#module-tkinter.dnd',
+ 'tkinter.filedialog': 'dialog#module-tkinter.filedialog',
+ 'tkinter.font': 'tkinter.font#module-tkinter.font',
+ 'tkinter.messagebox': 'tkinter.messagebox#module-tkinter.messagebox',
+ 'tkinter.scrolledtext': 'tkinter.scrolledtext#module-tkinter.scrolledtext',
+ 'tkinter.simpledialog': 'dialog#module-tkinter.simpledialog',
+ 'tkinter.ttk': 'tkinter.ttk#module-tkinter.ttk',
+ 'token': 'token#module-token',
+ 'tokenize': 'tokenize#module-tokenize',
+ 'tomllib': 'tomllib#module-tomllib',
+ 'trace': 'trace#module-trace',
+ 'traceback': 'traceback#module-traceback',
+ 'tracemalloc': 'tracemalloc#module-tracemalloc',
+ 'tty': 'tty#module-tty',
+ 'turtle': 'turtle#module-turtle',
+ 'turtledemo': 'turtle#module-turtledemo',
+ 'types': 'types#module-types',
+ 'typing': 'typing#module-typing',
+ 'unicodedata': 'unicodedata#module-unicodedata',
+ 'unittest': 'unittest#module-unittest',
+ 'unittest.mock': 'unittest.mock#module-unittest.mock',
+ 'urllib': 'urllib#module-urllib',
+ 'urllib.error': 'urllib.error#module-urllib.error',
+ 'urllib.parse': 'urllib.parse#module-urllib.parse',
+ 'urllib.request': 'urllib.request#module-urllib.request',
+ 'urllib.response': 'urllib.request#module-urllib.response',
+ 'urllib.robotparser': 'urllib.robotparser#module-urllib.robotparser',
+ 'usercustomize': 'site#module-usercustomize',
+ 'uu': 'uu#module-uu',
+ 'uuid': 'uuid#module-uuid',
+ 'venv': 'venv#module-venv',
+ 'warnings': 'warnings#module-warnings',
+ 'wave': 'wave#module-wave',
+ 'weakref': 'weakref#module-weakref',
+ 'webbrowser': 'webbrowser#module-webbrowser',
+ 'winreg': 'winreg#module-winreg',
+ 'winsound': 'winsound#module-winsound',
+ 'wsgiref': 'wsgiref#module-wsgiref',
+ 'wsgiref.handlers': 'wsgiref#module-wsgiref.handlers',
+ 'wsgiref.headers': 'wsgiref#module-wsgiref.headers',
+ 'wsgiref.simple_server': 'wsgiref#module-wsgiref.simple_server',
+ 'wsgiref.types': 'wsgiref#module-wsgiref.types',
+ 'wsgiref.util': 'wsgiref#module-wsgiref.util',
+ 'wsgiref.validate': 'wsgiref#module-wsgiref.validate',
+ 'xdrlib': 'xdrlib#module-xdrlib',
+ 'xml': 'xml#module-xml',
+ 'xml.dom': 'xml.dom#module-xml.dom',
+ 'xml.dom.minidom': 'xml.dom.minidom#module-xml.dom.minidom',
+ 'xml.dom.pulldom': 'xml.dom.pulldom#module-xml.dom.pulldom',
+ 'xml.etree.ElementInclude': 'xml.etree.elementtree#module-xml.etree.ElementInclude',
+ 'xml.etree.ElementTree': 'xml.etree.elementtree#module-xml.etree.ElementTree',
+ 'xml.parsers.expat': 'pyexpat#module-xml.parsers.expat',
+ 'xml.parsers.expat.errors': 'pyexpat#module-xml.parsers.expat.errors',
+ 'xml.parsers.expat.model': 'pyexpat#module-xml.parsers.expat.model',
+ 'xml.sax': 'xml.sax#module-xml.sax',
+ 'xml.sax.handler': 'xml.sax.handler#module-xml.sax.handler',
+ 'xml.sax.saxutils': 'xml.sax.utils#module-xml.sax.saxutils',
+ 'xml.sax.xmlreader': 'xml.sax.reader#module-xml.sax.xmlreader',
+ 'xmlrpc': 'xmlrpc#module-xmlrpc',
+ 'xmlrpc.client': 'xmlrpc.client#module-xmlrpc.client',
+ 'xmlrpc.server': 'xmlrpc.server#module-xmlrpc.server',
+ 'zipapp': 'zipapp#module-zipapp',
+ 'zipfile': 'zipfile#module-zipfile',
+ 'zipimport': 'zipimport#module-zipimport',
+ 'zlib': 'zlib#module-zlib',
+ 'zoneinfo': 'zoneinfo#module-zoneinfo',
+}
diff --git a/contrib/tools/python3/Lib/pydoc_data/topics.py b/contrib/tools/python3/Lib/pydoc_data/topics.py
index fdbe8106ade..839d454df6a 100644
--- a/contrib/tools/python3/Lib/pydoc_data/topics.py
+++ b/contrib/tools/python3/Lib/pydoc_data/topics.py
@@ -1,4 +1,4 @@
-# Autogenerated by Sphinx on Fri Dec 5 17:06:29 2025
+# Autogenerated by Sphinx on Tue Feb 3 18:53:22 2026
# as part of the release process.
topics = {
@@ -1939,7 +1939,7 @@ ensures that the type of the target "e" is consistently
... except* BlockingIOError as e:
... print(repr(e))
...
- ExceptionGroup('', (BlockingIOError()))
+ ExceptionGroup('', (BlockingIOError(),))
"break", "continue" and "return" cannot appear in an "except*" clause.
@@ -5386,7 +5386,9 @@ The available presentation types for "float" and "Decimal" values are:
| | With no precision given, uses a precision of "6" digits |
| | after the decimal point for "float", and shows all |
| | coefficient digits for "Decimal". If "p=0", the decimal |
- | | point is omitted unless the "#" option is used. |
+ | | point is omitted unless the "#" option is used. For |
+ | | "float", the exponent always contains at least two digits, |
+ | | and is zero if the value is zero. |
+-----------+------------------------------------------------------------+
| "'E'" | Scientific notation. Same as "'e'" except it uses an upper |
| | case ‘E’ as the separator character. |
@@ -9053,7 +9055,12 @@ str.casefold()
it is intended to remove all case distinctions in a string. For
example, the German lowercase letter "'ß'" is equivalent to ""ss"".
Since it is already lowercase, "lower()" would do nothing to "'ß'";
- "casefold()" converts it to ""ss"".
+ "casefold()" converts it to ""ss"". For example:
+
+ >>> 'straße'.lower()
+ 'straße'
+ >>> 'straße'.casefold()
+ 'strasse'
The casefolding algorithm is described in section 3.13 ‘Default
Case Folding’ of the Unicode Standard.
@@ -9242,7 +9249,18 @@ str.format_map(mapping, /)
str.index(sub[, start[, end]])
Like "find()", but raise "ValueError" when the substring is not
- found.
+ found. For example:
+
+ >>> 'spam, spam, spam'.index('spam')
+ 0
+ >>> 'spam, spam, spam'.index('eggs')
+ Traceback (most recent call last):
+ File "<python-input-0>", line 1, in <module>
+ 'spam, spam, spam'.index('eggs')
+ ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
+ ValueError: substring not found
+
+ See also "rindex()".
str.isalnum()
@@ -9341,7 +9359,19 @@ str.isnumeric()
that have the Unicode numeric value property, e.g. U+2155, VULGAR
FRACTION ONE FIFTH. Formally, numeric characters are those with
the property value Numeric_Type=Digit, Numeric_Type=Decimal or
- Numeric_Type=Numeric.
+ Numeric_Type=Numeric. For example:
+
+ >>> '0123456789'.isnumeric()
+ True
+ >>> '٠١٢٣٤٥٦٧٨٩'.isnumeric() # Arabic-indic digit zero to nine
+ True
+ >>> 'â…•'.isnumeric() # Vulgar fraction one fifth
+ True
+ >>> '²'.isdecimal(), '²'.isdigit(), '²'.isnumeric()
+ (False, True, True)
+
+ See also "isdecimal()" and "isdigit()". Numeric characters are a
+ superset of decimal numbers.
str.isprintable()
@@ -9359,6 +9389,13 @@ str.isprintable()
plus the ASCII space 0x20. Nonprintable characters are those in
group Separator or Other (Z or C), except the ASCII space.
+ For example:
+
+ >>> ''.isprintable(), ' '.isprintable()
+ (True, True)
+ >>> '\t'.isprintable(), '\n'.isprintable()
+ (False, False)
+
str.isspace()
Return "True" if there are only whitespace characters in the string
@@ -9424,10 +9461,24 @@ str.ljust(width, fillchar=' ', /)
space). The original string is returned if *width* is less than or
equal to "len(s)".
+ For example:
+
+ >>> 'Python'.ljust(10)
+ 'Python '
+ >>> 'Python'.ljust(10, '.')
+ 'Python....'
+ >>> 'Monty Python'.ljust(10, '.')
+ 'Monty Python'
+
+ See also "rjust()".
+
str.lower()
Return a copy of the string with all the cased characters [4]
- converted to lowercase.
+ converted to lowercase. For example:
+
+ >>> 'Lower Method Example'.lower()
+ 'lower method example'
The lowercasing algorithm used is described in section 3.13
‘Default Case Folding’ of the Unicode Standard.
@@ -9491,6 +9542,8 @@ str.removeprefix(prefix, /)
Added in version 3.9.
+ See also "removesuffix()" and "startswith()".
+
str.removesuffix(suffix, /)
If the string ends with the *suffix* string and that *suffix* is
@@ -9504,12 +9557,19 @@ str.removesuffix(suffix, /)
Added in version 3.9.
+ See also "removeprefix()" and "endswith()".
+
str.replace(old, new, /, count=-1)
Return a copy of the string with all occurrences of substring *old*
replaced by *new*. If *count* is given, only the first *count*
occurrences are replaced. If *count* is not specified or "-1", then
- all occurrences are replaced.
+ all occurrences are replaced. For example:
+
+ >>> 'spam, spam, spam'.replace('spam', 'eggs')
+ 'eggs, eggs, eggs'
+ >>> 'spam, spam, spam'.replace('spam', 'eggs', 1)
+ 'eggs, spam, spam'
Changed in version 3.13: *count* is now supported as a keyword
argument.
@@ -9519,12 +9579,30 @@ str.rfind(sub[, start[, end]])
Return the highest index in the string where substring *sub* is
found, such that *sub* is contained within "s[start:end]".
Optional arguments *start* and *end* are interpreted as in slice
- notation. Return "-1" on failure.
+ notation. Return "-1" on failure. For example:
+
+ >>> 'spam, spam, spam'.rfind('sp')
+ 12
+ >>> 'spam, spam, spam'.rfind('sp', 0, 10)
+ 6
+
+ See also "find()" and "rindex()".
str.rindex(sub[, start[, end]])
Like "rfind()" but raises "ValueError" when the substring *sub* is
- not found.
+ not found. For example:
+
+ >>> 'spam, spam, spam'.rindex('spam')
+ 12
+ >>> 'spam, spam, spam'.rindex('eggs')
+ Traceback (most recent call last):
+ File "<stdin-0>", line 1, in <module>
+ 'spam, spam, spam'.rindex('eggs')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
+ ValueError: substring not found
+
+ See also "index()" and "find()".
str.rjust(width, fillchar=' ', /)
@@ -9541,6 +9619,17 @@ str.rpartition(sep, /)
found, return a 3-tuple containing two empty strings, followed by
the string itself.
+ For example:
+
+ >>> 'Monty Python'.rpartition(' ')
+ ('Monty', ' ', 'Python')
+ >>> "Monty Python's Flying Circus".rpartition(' ')
+ ("Monty Python's Flying", ' ', 'Circus')
+ >>> 'Monty Python'.rpartition('-')
+ ('', '', 'Monty Python')
+
+ See also "partition()".
+
str.rsplit(sep=None, maxsplit=-1)
Return a list of the words in the string, using *sep* as the
@@ -10227,7 +10316,7 @@ ensures that the type of the target "e" is consistently
... except* BlockingIOError as e:
... print(repr(e))
...
- ExceptionGroup('', (BlockingIOError()))
+ ExceptionGroup('', (BlockingIOError(),))
"break", "continue" and "return" cannot appear in an "except*" clause.
@@ -10611,6 +10700,10 @@ Special read-only attributes
+----------------------------------------------------+----------------------------------------------------+
| Attribute | Meaning |
|====================================================|====================================================|
+| function.__builtins__ | A reference to the "dictionary" that holds the |
+| | function’s builtins namespace. Added in version |
+| | 3.10. |
++----------------------------------------------------+----------------------------------------------------+
| function.__globals__ | A reference to the "dictionary" that holds the |
| | function’s global variables – the global namespace |
| | of the module in which the function was defined. |
@@ -11672,10 +11765,6 @@ class dict(iterable, /, **kwargs)
the keyword argument replaces the value from the positional
argument.
- Providing keyword arguments as in the first example only works for
- keys that are valid Python identifiers. Otherwise, any valid keys
- can be used.
-
Dictionaries compare equal if and only if they have the same "(key,
value)" pairs (regardless of ordering). Order comparisons (‘<’,
‘<=’, ‘>=’, ‘>’) raise "TypeError". To illustrate dictionary
@@ -12188,10 +12277,17 @@ Notes:
note that "-0" is still "0".
4. The slice of *s* from *i* to *j* is defined as the sequence of
- items with index *k* such that "i <= k < j". If *i* or *j* is
- greater than "len(s)", use "len(s)". If *i* is omitted or "None",
- use "0". If *j* is omitted or "None", use "len(s)". If *i* is
- greater than or equal to *j*, the slice is empty.
+ items with index *k* such that "i <= k < j".
+
+ * If *i* is omitted or "None", use "0".
+
+ * If *j* is omitted or "None", use "len(s)".
+
+ * If *i* or *j* is less than "-len(s)", use "0".
+
+ * If *i* or *j* is greater than "len(s)", use "len(s)".
+
+ * If *i* is greater than or equal to *j*, the slice is empty.
5. The slice of *s* from *i* to *j* with step *k* is defined as the
sequence of items with index "x = i + n*k" such that "0 <= n <
diff --git a/contrib/tools/python3/Lib/ssl.py b/contrib/tools/python3/Lib/ssl.py
index 9a2563c1d84..d976ce7b91a 100644
--- a/contrib/tools/python3/Lib/ssl.py
+++ b/contrib/tools/python3/Lib/ssl.py
@@ -186,7 +186,7 @@ class _TLSContentType:
class _TLSAlertType:
"""Alert types for TLSContentType.ALERT messages
- See RFC 8466, section B.2
+ See RFC 8446, section B.2
"""
CLOSE_NOTIFY = 0
UNEXPECTED_MESSAGE = 10
diff --git a/contrib/tools/python3/Lib/stat.py b/contrib/tools/python3/Lib/stat.py
index 1b4ed1ebc94..81f694329bf 100644
--- a/contrib/tools/python3/Lib/stat.py
+++ b/contrib/tools/python3/Lib/stat.py
@@ -166,9 +166,14 @@ def filemode(mode):
perm = []
for index, table in enumerate(_filemode_table):
for bit, char in table:
- if mode & bit == bit:
- perm.append(char)
- break
+ if index == 0:
+ if S_IFMT(mode) == bit:
+ perm.append(char)
+ break
+ else:
+ if mode & bit == bit:
+ perm.append(char)
+ break
else:
if index == 0:
# Unknown filetype
diff --git a/contrib/tools/python3/Lib/subprocess.py b/contrib/tools/python3/Lib/subprocess.py
index 885f0092b53..3a8c7434d37 100644
--- a/contrib/tools/python3/Lib/subprocess.py
+++ b/contrib/tools/python3/Lib/subprocess.py
@@ -2143,7 +2143,7 @@ class Popen:
while selector.get_map():
timeout = self._remaining_time(endtime)
- if timeout is not None and timeout < 0:
+ if timeout is not None and timeout <= 0:
self._check_timeout(endtime, orig_timeout,
stdout, stderr,
skip_check_and_raise=True)
diff --git a/contrib/tools/python3/Lib/types.py b/contrib/tools/python3/Lib/types.py
index 1484c22ee9d..ff474c14144 100644
--- a/contrib/tools/python3/Lib/types.py
+++ b/contrib/tools/python3/Lib/types.py
@@ -261,10 +261,14 @@ class _GeneratorWrapper:
@property
def gi_yieldfrom(self):
return self.__wrapped.gi_yieldfrom
+ @property
+ def gi_suspended(self):
+ return self.__wrapped.gi_suspended
cr_code = gi_code
cr_frame = gi_frame
cr_running = gi_running
cr_await = gi_yieldfrom
+ cr_suspended = gi_suspended
def __next__(self):
return next(self.__wrapped)
def __iter__(self):
diff --git a/contrib/tools/python3/Lib/typing.py b/contrib/tools/python3/Lib/typing.py
index 35ffaabc719..67b1ef329d5 100644
--- a/contrib/tools/python3/Lib/typing.py
+++ b/contrib/tools/python3/Lib/typing.py
@@ -1639,9 +1639,9 @@ class _SpecialGenericAlias(_NotIterable, _BaseGenericAlias, _root=True):
self._nparams = nparams
self._defaults = defaults
if origin.__module__ == 'builtins':
- self.__doc__ = f'A generic version of {origin.__qualname__}.'
+ self.__doc__ = f'Deprecated alias to {origin.__qualname__}.'
else:
- self.__doc__ = f'A generic version of {origin.__module__}.{origin.__qualname__}.'
+ self.__doc__ = f'Deprecated alias to {origin.__module__}.{origin.__qualname__}.'
@_tp_cache
def __getitem__(self, params):
diff --git a/contrib/tools/python3/Lib/unittest/mock.py b/contrib/tools/python3/Lib/unittest/mock.py
index 6cec61ff35c..1dd7735d150 100644
--- a/contrib/tools/python3/Lib/unittest/mock.py
+++ b/contrib/tools/python3/Lib/unittest/mock.py
@@ -1174,7 +1174,6 @@ class CallableMixin(Base):
def _increment_mock_call(self, /, *args, **kwargs):
self.called = True
- self.call_count += 1
# handle call_args
# needs to be set here so assertions on call arguments pass before
@@ -1182,6 +1181,7 @@ class CallableMixin(Base):
_call = _Call((args, kwargs), two=True)
self.call_args = _call
self.call_args_list.append(_call)
+ self.call_count = len(self.call_args_list)
# initial stuff for method_calls:
do_method_calls = self._mock_parent is not None
diff --git a/contrib/tools/python3/Lib/urllib/request.py b/contrib/tools/python3/Lib/urllib/request.py
index 21d76913feb..3d864f1d92f 100644
--- a/contrib/tools/python3/Lib/urllib/request.py
+++ b/contrib/tools/python3/Lib/urllib/request.py
@@ -1636,6 +1636,11 @@ class DataHandler(BaseHandler):
scheme, data = url.split(":",1)
mediatype, data = data.split(",",1)
+ # Disallow control characters within mediatype.
+ if re.search(r"[\x00-\x1F\x7F]", mediatype):
+ raise ValueError(
+ "Control characters not allowed in data: mediatype")
+
# even base64 encoded data URLs might be quoted so unquote in any case:
data = unquote_to_bytes(data)
if mediatype.endswith(";base64"):
diff --git a/contrib/tools/python3/Lib/wsgiref/headers.py b/contrib/tools/python3/Lib/wsgiref/headers.py
index fab851c5a44..fd98e85d754 100644
--- a/contrib/tools/python3/Lib/wsgiref/headers.py
+++ b/contrib/tools/python3/Lib/wsgiref/headers.py
@@ -9,6 +9,7 @@ written by Barry Warsaw.
# existence of which force quoting of the parameter value.
import re
tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
+_control_chars_re = re.compile(r'[\x00-\x1F\x7F]')
def _formatparam(param, value=None, quote=1):
"""Convenience function to format and return a key=value pair.
@@ -41,6 +42,8 @@ class Headers:
def _convert_string_type(self, value):
"""Convert/check value type."""
if type(value) is str:
+ if _control_chars_re.search(value):
+ raise ValueError("Control characters not allowed in headers")
return value
raise AssertionError("Header names/values must be"
" of type str (got {0})".format(repr(value)))
diff --git a/contrib/tools/python3/Lib/xml/dom/minidom.py b/contrib/tools/python3/Lib/xml/dom/minidom.py
index 0a2ccc00f18..16b33b90184 100644
--- a/contrib/tools/python3/Lib/xml/dom/minidom.py
+++ b/contrib/tools/python3/Lib/xml/dom/minidom.py
@@ -364,6 +364,7 @@ class Attr(Node):
def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
prefix=None):
self.ownerElement = None
+ self.ownerDocument = None
self._name = qName
self.namespaceURI = namespaceURI
self._prefix = prefix
@@ -689,6 +690,7 @@ class Element(Node):
def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
localName=None):
+ self.ownerDocument = None
self.parentNode = None
self.tagName = self.nodeName = tagName
self.prefix = prefix
diff --git a/contrib/tools/python3/Lib/ya.make b/contrib/tools/python3/Lib/ya.make
index 9fccb680aad..3d9168d587d 100644
--- a/contrib/tools/python3/Lib/ya.make
+++ b/contrib/tools/python3/Lib/ya.make
@@ -4,9 +4,9 @@ ENABLE(PYBUILD_NO_PY)
PY3_LIBRARY()
-VERSION(3.13.11)
+VERSION(3.13.12)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.11.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.12.tar.gz)
LICENSE(Python-2.0)
@@ -428,6 +428,7 @@ PY_SRCS(
pyclbr.py
pydoc.py
pydoc_data/__init__.py
+ pydoc_data/module_docs.py
pydoc_data/topics.py
queue.py
quopri.py
diff --git a/contrib/tools/python3/Lib/zoneinfo/_common.py b/contrib/tools/python3/Lib/zoneinfo/_common.py
index 03cc42149f9..59f3f0ce853 100644
--- a/contrib/tools/python3/Lib/zoneinfo/_common.py
+++ b/contrib/tools/python3/Lib/zoneinfo/_common.py
@@ -118,11 +118,10 @@ def load_data(fobj):
c = fobj.read(1) # Should be \n
assert c == b"\n", c
- tz_bytes = b""
- while (c := fobj.read(1)) != b"\n":
- tz_bytes += c
-
- tz_str = tz_bytes
+ line = fobj.readline()
+ if not line.endswith(b"\n"):
+ raise ValueError("Invalid TZif file: unexpected end of file")
+ tz_str = line.rstrip(b"\n")
else:
tz_str = None
diff --git a/contrib/tools/python3/Modules/_collectionsmodule.c b/contrib/tools/python3/Modules/_collectionsmodule.c
index 2c30e5c70a6..f5fc0d02a16 100644
--- a/contrib/tools/python3/Modules/_collectionsmodule.c
+++ b/contrib/tools/python3/Modules/_collectionsmodule.c
@@ -2203,11 +2203,11 @@ defdict_missing(defdictobject *dd, PyObject *key)
value = _PyObject_CallNoArgs(factory);
if (value == NULL)
return value;
- if (PyObject_SetItem((PyObject *)dd, key, value) < 0) {
- Py_DECREF(value);
- return NULL;
- }
- return value;
+ PyObject *result = NULL;
+ (void)PyDict_SetDefaultRef((PyObject *)dd, key, value, &result);
+ // 'result' is NULL, or a strong reference to 'value' or 'dd[key]'
+ Py_DECREF(value);
+ return result;
}
static inline PyObject*
@@ -2549,7 +2549,12 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping,
if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) < 0)
goto done;
} else {
+ /* oldval is a borrowed reference. Keep it alive across
+ PyNumber_Add(), which can execute arbitrary user code and
+ mutate (or even clear) the underlying dict. */
+ Py_INCREF(oldval);
newval = PyNumber_Add(oldval, one);
+ Py_DECREF(oldval);
if (newval == NULL)
goto done;
if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) < 0)
diff --git a/contrib/tools/python3/Modules/_ctypes/_ctypes.c b/contrib/tools/python3/Modules/_ctypes/_ctypes.c
index ad088b0ce8e..aac812813d9 100644
--- a/contrib/tools/python3/Modules/_ctypes/_ctypes.c
+++ b/contrib/tools/python3/Modules/_ctypes/_ctypes.c
@@ -1338,7 +1338,13 @@ PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls,
/* If we expect POINTER(<type>), but receive a <type> instance, accept
it by calling byref(<type>).
*/
- assert(typeinfo->proto);
+ if (typeinfo->proto == NULL) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "cannot convert argument: POINTER _type_ type is not set"
+ );
+ return NULL;
+ }
switch (PyObject_IsInstance(value, typeinfo->proto)) {
case 1:
Py_INCREF(value); /* _byref steals a refcount */
@@ -4273,6 +4279,7 @@ _build_result(PyObject *result, PyObject *callargs,
v = PyTuple_GET_ITEM(callargs, i);
v = PyObject_CallMethodNoArgs(v, &_Py_ID(__ctypes_from_outparam__));
if (v == NULL || numretvals == 1) {
+ Py_XDECREF(tup);
Py_DECREF(callargs);
return v;
}
diff --git a/contrib/tools/python3/Modules/_decimal/_decimal.c b/contrib/tools/python3/Modules/_decimal/_decimal.c
index d1fbfd7d303..cbe7af13240 100644
--- a/contrib/tools/python3/Modules/_decimal/_decimal.c
+++ b/contrib/tools/python3/Modules/_decimal/_decimal.c
@@ -3462,7 +3462,8 @@ dec_format(PyObject *dec, PyObject *args)
if (size > 0 && fmt[size-1] == 'N') {
if (PyErr_WarnEx(PyExc_DeprecationWarning,
- "Format specifier 'N' is deprecated", 1) < 0) {
+ "Format specifier 'N' is deprecated and "
+ "slated for removal in Python 3.18", 1) < 0) {
return NULL;
}
}
@@ -5922,10 +5923,15 @@ _decimal_exec(PyObject *m)
/* DecimalTuple */
ASSIGN_PTR(collections, PyImport_ImportModule("collections"));
- ASSIGN_PTR(state->DecimalTuple, (PyTypeObject *)PyObject_CallMethod(collections,
- "namedtuple", "(ss)", "DecimalTuple",
- "sign digits exponent"));
-
+ ASSIGN_PTR(obj, PyObject_CallMethod(collections, "namedtuple", "(ss)",
+ "DecimalTuple",
+ "sign digits exponent"));
+ if (!PyType_Check(obj)) {
+ PyErr_SetString(PyExc_TypeError,
+ "type is expected from namedtuple call");
+ goto error;
+ }
+ ASSIGN_PTR(state->DecimalTuple, (PyTypeObject *)obj);
ASSIGN_PTR(obj, PyUnicode_FromString("decimal"));
CHECK_INT(PyDict_SetItemString(state->DecimalTuple->tp_dict, "__module__", obj));
Py_CLEAR(obj);
diff --git a/contrib/tools/python3/Modules/_elementtree.c b/contrib/tools/python3/Modules/_elementtree.c
index 020b7454add..dfa03663c38 100644
--- a/contrib/tools/python3/Modules/_elementtree.c
+++ b/contrib/tools/python3/Modules/_elementtree.c
@@ -1803,16 +1803,20 @@ element_subscr(PyObject* self_, PyObject* item)
return element_getitem(self_, i);
}
else if (PySlice_Check(item)) {
+ // Note: 'slicelen' is computed once we are sure that 'self->extra'
+ // cannot be mutated by user-defined code.
+ // See https://github.com/python/cpython/issues/143200.
Py_ssize_t start, stop, step, slicelen, i;
size_t cur;
PyObject* list;
- if (!self->extra)
- return PyList_New(0);
-
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+
+ if (self->extra == NULL) {
+ return PyList_New(0);
+ }
slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
step);
@@ -1855,28 +1859,26 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
return element_setitem(self_, i, value);
}
else if (PySlice_Check(item)) {
+ // Note: 'slicelen' is computed once we are sure that 'self->extra'
+ // cannot be mutated by user-defined code.
+ // See https://github.com/python/cpython/issues/143200.
Py_ssize_t start, stop, step, slicelen, newlen, i;
size_t cur;
PyObject* recycle = NULL;
PyObject* seq;
- if (!self->extra) {
- if (create_extra(self, NULL) < 0)
- return -1;
- }
-
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
- slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
- step);
if (value == NULL) {
/* Delete slice */
- size_t cur;
- Py_ssize_t i;
-
+ if (self->extra == NULL) {
+ return 0;
+ }
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
if (slicelen <= 0)
return 0;
@@ -1945,8 +1947,16 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
}
newlen = PySequence_Fast_GET_SIZE(seq);
- if (step != 1 && newlen != slicelen)
- {
+ if (self->extra == NULL) {
+ if (create_extra(self, NULL) < 0) {
+ Py_DECREF(seq);
+ return -1;
+ }
+ }
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
+
+ if (step != 1 && newlen != slicelen) {
Py_DECREF(seq);
PyErr_Format(PyExc_ValueError,
"attempt to assign sequence of size %zd "
diff --git a/contrib/tools/python3/Modules/_io/bufferedio.c b/contrib/tools/python3/Modules/_io/bufferedio.c
index 65d69d0d5e1..2e8566168de 100644
--- a/contrib/tools/python3/Modules/_io/bufferedio.c
+++ b/contrib/tools/python3/Modules/_io/bufferedio.c
@@ -1486,8 +1486,8 @@ buffered_iternext(buffered *self)
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
tp = Py_TYPE(self);
- if (Py_IS_TYPE(tp, state->PyBufferedReader_Type) ||
- Py_IS_TYPE(tp, state->PyBufferedRandom_Type))
+ if (tp == state->PyBufferedReader_Type ||
+ tp == state->PyBufferedRandom_Type)
{
/* Skip method call overhead for speed */
line = _buffered_readline(self, -1);
diff --git a/contrib/tools/python3/Modules/_io/bytesio.c b/contrib/tools/python3/Modules/_io/bytesio.c
index b7aac773158..e149823afd3 100644
--- a/contrib/tools/python3/Modules/_io/bytesio.c
+++ b/contrib/tools/python3/Modules/_io/bytesio.c
@@ -180,18 +180,18 @@ resize_buffer(bytesio *self, size_t size)
Py_NO_INLINE static Py_ssize_t
write_bytes(bytesio *self, PyObject *b)
{
- if (check_closed(self)) {
- return -1;
- }
- if (check_exports(self)) {
- return -1;
- }
-
Py_buffer buf;
+ Py_ssize_t len;
if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0) {
return -1;
}
- Py_ssize_t len = buf.len;
+
+ if (check_closed(self) || check_exports(self)) {
+ len = -1;
+ goto done;
+ }
+
+ len = buf.len;
if (len == 0) {
goto done;
}
diff --git a/contrib/tools/python3/Modules/_io/textio.c b/contrib/tools/python3/Modules/_io/textio.c
index 047d0fdfc76..db6c709c00c 100644
--- a/contrib/tools/python3/Modules/_io/textio.c
+++ b/contrib/tools/python3/Modules/_io/textio.c
@@ -3133,6 +3133,9 @@ _io_TextIOWrapper_close_impl(textio *self)
if (r > 0) {
Py_RETURN_NONE; /* stream already closed */
}
+ if (self->detached) {
+ Py_RETURN_NONE; /* gh-142594 null pointer issue */
+ }
else {
PyObject *exc = NULL;
if (self->finalizing) {
diff --git a/contrib/tools/python3/Modules/_json.c b/contrib/tools/python3/Modules/_json.c
index cc41b9ab867..afefc71bfbd 100644
--- a/contrib/tools/python3/Modules/_json.c
+++ b/contrib/tools/python3/Modules/_json.c
@@ -308,11 +308,12 @@ raise_errmsg(const char *msg, PyObject *s, Py_ssize_t end)
PyObject *exc;
exc = PyObject_CallFunction(JSONDecodeError, "zOn", msg, s, end);
- Py_DECREF(JSONDecodeError);
if (exc) {
PyErr_SetObject(JSONDecodeError, exc);
Py_DECREF(exc);
}
+
+ Py_DECREF(JSONDecodeError);
}
static void
diff --git a/contrib/tools/python3/Modules/_pickle.c b/contrib/tools/python3/Modules/_pickle.c
index 409b31872d5..27a6d9e8c6a 100644
--- a/contrib/tools/python3/Modules/_pickle.c
+++ b/contrib/tools/python3/Modules/_pickle.c
@@ -640,6 +640,7 @@ typedef struct PicklerObject {
int fast_nesting;
int fix_imports; /* Indicate whether Pickler should fix
the name of globals for Python 2.x. */
+ int running; /* True when a method of Pickler is executing. */
PyObject *fast_memo;
PyObject *buffer_callback; /* Callback for out-of-band buffers, or NULL */
} PicklerObject;
@@ -683,6 +684,8 @@ typedef struct UnpicklerObject {
int proto; /* Protocol of the pickle loaded. */
int fix_imports; /* Indicate whether Unpickler should fix
the name of globals pickled by Python 2.x. */
+ int running; /* True when a method of Unpickler is executing. */
+
} UnpicklerObject;
typedef struct {
@@ -695,6 +698,32 @@ typedef struct {
UnpicklerObject *unpickler;
} UnpicklerMemoProxyObject;
+#define BEGIN_USING_PICKLER(SELF, RET) do { \
+ if ((SELF)->running) { \
+ PyErr_SetString(PyExc_RuntimeError, \
+ "Pickler object is already used"); \
+ return (RET); \
+ } \
+ (SELF)->running = 1; \
+ } while (0)
+
+#define END_USING_PICKLER(SELF) do { \
+ (SELF)->running = 0; \
+ } while (0)
+
+#define BEGIN_USING_UNPICKLER(SELF, RET) do { \
+ if ((SELF)->running) { \
+ PyErr_SetString(PyExc_RuntimeError, \
+ "Unpickler object is already used"); \
+ return (RET); \
+ } \
+ (SELF)->running = 1; \
+ } while (0)
+
+#define END_USING_UNPICKLER(SELF) do { \
+ (SELF)->running = 0; \
+ } while (0)
+
/* Forward declarations */
static int save(PickleState *state, PicklerObject *, PyObject *, int);
static int save_reduce(PickleState *, PicklerObject *, PyObject *, PyObject *);
@@ -1124,6 +1153,7 @@ _Pickler_New(PickleState *st)
self->fast = 0;
self->fast_nesting = 0;
self->fix_imports = 0;
+ self->running = 0;
self->fast_memo = NULL;
self->buffer_callback = NULL;
@@ -1627,6 +1657,7 @@ _Unpickler_New(PyObject *module)
self->marks_size = 0;
self->proto = 0;
self->fix_imports = 0;
+ self->running = 0;
PyObject_GC_Track(self);
return self;
@@ -2523,53 +2554,61 @@ save_picklebuffer(PickleState *st, PicklerObject *self, PyObject *obj)
"PickleBuffer can only be pickled with protocol >= 5");
return -1;
}
- const Py_buffer* view = PyPickleBuffer_GetBuffer(obj);
- if (view == NULL) {
+ Py_buffer view;
+ if (PyObject_GetBuffer(obj, &view, PyBUF_FULL_RO) != 0) {
return -1;
}
- if (view->suboffsets != NULL || !PyBuffer_IsContiguous(view, 'A')) {
+ if (view.suboffsets != NULL || !PyBuffer_IsContiguous(&view, 'A')) {
PyErr_SetString(st->PicklingError,
"PickleBuffer can not be pickled when "
"pointing to a non-contiguous buffer");
- return -1;
+ goto error;
}
+
+ int rc = 0;
int in_band = 1;
if (self->buffer_callback != NULL) {
PyObject *ret = PyObject_CallOneArg(self->buffer_callback, obj);
if (ret == NULL) {
- return -1;
+ goto error;
}
in_band = PyObject_IsTrue(ret);
Py_DECREF(ret);
if (in_band == -1) {
- return -1;
+ goto error;
}
}
if (in_band) {
/* Write data in-band */
- if (view->readonly) {
- return _save_bytes_data(st, self, obj, (const char *)view->buf,
- view->len);
+ if (view.readonly) {
+ rc = _save_bytes_data(st, self, obj, (const char *)view.buf,
+ view.len);
}
else {
- return _save_bytearray_data(st, self, obj, (const char *)view->buf,
- view->len);
+ rc = _save_bytearray_data(st, self, obj, (const char *)view.buf,
+ view.len);
}
}
else {
/* Write data out-of-band */
const char next_buffer_op = NEXT_BUFFER;
if (_Pickler_Write(self, &next_buffer_op, 1) < 0) {
- return -1;
+ goto error;
}
- if (view->readonly) {
+ if (view.readonly) {
const char readonly_buffer_op = READONLY_BUFFER;
if (_Pickler_Write(self, &readonly_buffer_op, 1) < 0) {
- return -1;
+ goto error;
}
}
}
- return 0;
+
+ PyBuffer_Release(&view);
+ return rc;
+
+error:
+ PyBuffer_Release(&view);
+ return -1;
}
/* A copy of PyUnicode_AsRawUnicodeEscapeString() that also translates
@@ -4603,17 +4642,23 @@ _pickle_Pickler_dump_impl(PicklerObject *self, PyTypeObject *cls,
Py_TYPE(self)->tp_name);
return NULL;
}
+ BEGIN_USING_PICKLER(self, NULL);
- if (_Pickler_ClearBuffer(self) < 0)
- return NULL;
-
- if (dump(st, self, obj) < 0)
- return NULL;
-
- if (_Pickler_FlushToFile(self) < 0)
- return NULL;
-
+ if (_Pickler_ClearBuffer(self) < 0) {
+ goto error;
+ }
+ if (dump(st, self, obj) < 0) {
+ goto error;
+ }
+ if (_Pickler_FlushToFile(self) < 0) {
+ goto error;
+ }
+ END_USING_PICKLER(self);
Py_RETURN_NONE;
+
+error:
+ END_USING_PICKLER(self);
+ return NULL;
}
/*[clinic input]
@@ -4752,47 +4797,54 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file,
PyObject *buffer_callback)
/*[clinic end generated code: output=0abedc50590d259b input=a7c969699bf5dad3]*/
{
+ BEGIN_USING_PICKLER(self, -1);
/* In case of multiple __init__() calls, clear previous content. */
if (self->write != NULL)
(void)Pickler_clear(self);
- if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0)
- return -1;
-
- if (_Pickler_SetOutputStream(self, file) < 0)
- return -1;
-
- if (_Pickler_SetBufferCallback(self, buffer_callback) < 0)
- return -1;
-
+ if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0) {
+ goto error;
+ }
+ if (_Pickler_SetOutputStream(self, file) < 0) {
+ goto error;
+ }
+ if (_Pickler_SetBufferCallback(self, buffer_callback) < 0) {
+ goto error;
+ }
/* memo and output_buffer may have already been created in _Pickler_New */
if (self->memo == NULL) {
self->memo = PyMemoTable_New();
- if (self->memo == NULL)
- return -1;
+ if (self->memo == NULL) {
+ goto error;
+ }
}
self->output_len = 0;
if (self->output_buffer == NULL) {
self->max_output_len = WRITE_BUF_SIZE;
self->output_buffer = PyBytes_FromStringAndSize(NULL,
self->max_output_len);
- if (self->output_buffer == NULL)
- return -1;
+ if (self->output_buffer == NULL) {
+ goto error;
+ }
}
self->fast = 0;
self->fast_nesting = 0;
self->fast_memo = NULL;
- if (self->dispatch_table != NULL) {
- return 0;
- }
- if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(dispatch_table),
- &self->dispatch_table) < 0) {
- return -1;
+ if (self->dispatch_table == NULL) {
+ if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(dispatch_table),
+ &self->dispatch_table) < 0) {
+ goto error;
+ }
}
+ END_USING_PICKLER(self);
return 0;
+
+error:
+ END_USING_PICKLER(self);
+ return -1;
}
@@ -6979,22 +7031,22 @@ static PyObject *
_pickle_Unpickler_load_impl(UnpicklerObject *self, PyTypeObject *cls)
/*[clinic end generated code: output=cc88168f608e3007 input=f5d2f87e61d5f07f]*/
{
- UnpicklerObject *unpickler = (UnpicklerObject*)self;
-
PickleState *st = _Pickle_GetStateByClass(cls);
/* Check whether the Unpickler was initialized correctly. This prevents
segfaulting if a subclass overridden __init__ with a function that does
not call Unpickler.__init__(). Here, we simply ensure that self->read
is not NULL. */
- if (unpickler->read == NULL) {
+ if (self->read == NULL) {
PyErr_Format(st->UnpicklingError,
"Unpickler.__init__() was not called by %s.__init__()",
- Py_TYPE(unpickler)->tp_name);
+ Py_TYPE(self)->tp_name);
return NULL;
}
-
- return load(st, unpickler);
+ BEGIN_USING_UNPICKLER(self, NULL);
+ PyObject *res = load(st, self);
+ END_USING_UNPICKLER(self);
+ return res;
}
/* The name of find_class() is misleading. In newer pickle protocols, this
@@ -7235,35 +7287,41 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file,
const char *errors, PyObject *buffers)
/*[clinic end generated code: output=09f0192649ea3f85 input=ca4c1faea9553121]*/
{
+ BEGIN_USING_UNPICKLER(self, -1);
/* In case of multiple __init__() calls, clear previous content. */
if (self->read != NULL)
(void)Unpickler_clear(self);
- if (_Unpickler_SetInputStream(self, file) < 0)
- return -1;
-
- if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0)
- return -1;
-
- if (_Unpickler_SetBuffers(self, buffers) < 0)
- return -1;
-
+ if (_Unpickler_SetInputStream(self, file) < 0) {
+ goto error;
+ }
+ if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0) {
+ goto error;
+ }
+ if (_Unpickler_SetBuffers(self, buffers) < 0) {
+ goto error;
+ }
self->fix_imports = fix_imports;
PyTypeObject *tp = Py_TYPE(self);
PickleState *state = _Pickle_FindStateByType(tp);
self->stack = (Pdata *)Pdata_New(state);
- if (self->stack == NULL)
- return -1;
-
+ if (self->stack == NULL) {
+ goto error;
+ }
self->memo_size = 32;
self->memo = _Unpickler_NewMemo(self->memo_size);
- if (self->memo == NULL)
- return -1;
-
+ if (self->memo == NULL) {
+ goto error;
+ }
self->proto = 0;
+ END_USING_UNPICKLER(self);
return 0;
+
+error:
+ END_USING_UNPICKLER(self);
+ return -1;
}
diff --git a/contrib/tools/python3/Modules/_sqlite/connection.c b/contrib/tools/python3/Modules/_sqlite/connection.c
index a359fdc855c..b83dc9ae0cc 100644
--- a/contrib/tools/python3/Modules/_sqlite/connection.c
+++ b/contrib/tools/python3/Modules/_sqlite/connection.c
@@ -143,7 +143,8 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=67369db2faf80891]*/
static int _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
-static void free_callback_context(callback_context *ctx);
+static void incref_callback_context(callback_context *ctx);
+static void decref_callback_context(callback_context *ctx);
static void set_callback_context(callback_context **ctx_pp,
callback_context *ctx);
static int connection_close(pysqlite_Connection *self);
@@ -930,8 +931,9 @@ func_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
args = _pysqlite_build_py_params(context, argc, argv);
if (args) {
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
py_retval = PyObject_CallObject(ctx->callable, args);
+ decref_callback_context(ctx);
Py_DECREF(args);
}
@@ -958,7 +960,7 @@ step_callback(sqlite3_context *context, int argc, sqlite3_value **params)
PyObject* stepmethod = NULL;
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*));
if (aggregate_instance == NULL) {
@@ -996,6 +998,7 @@ step_callback(sqlite3_context *context, int argc, sqlite3_value **params)
}
error:
+ decref_callback_context(ctx);
Py_XDECREF(stepmethod);
Py_XDECREF(function_result);
@@ -1027,9 +1030,10 @@ final_callback(sqlite3_context *context)
PyObject *exc = PyErr_GetRaisedException();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
function_result = PyObject_CallMethodNoArgs(*aggregate_instance,
ctx->state->str_finalize);
+ decref_callback_context(ctx);
Py_DECREF(*aggregate_instance);
ok = 0;
@@ -1101,6 +1105,7 @@ create_callback_context(PyTypeObject *cls, PyObject *callable)
callback_context *ctx = PyMem_Malloc(sizeof(callback_context));
if (ctx != NULL) {
PyObject *module = PyType_GetModule(cls);
+ ctx->refcount = 1;
ctx->callable = Py_NewRef(callable);
ctx->module = Py_NewRef(module);
ctx->state = pysqlite_get_state(module);
@@ -1112,11 +1117,33 @@ static void
free_callback_context(callback_context *ctx)
{
assert(ctx != NULL);
+ assert(ctx->refcount == 0);
Py_XDECREF(ctx->callable);
Py_XDECREF(ctx->module);
PyMem_Free(ctx);
}
+static inline void
+incref_callback_context(callback_context *ctx)
+{
+ assert(PyGILState_Check());
+ assert(ctx != NULL);
+ assert(ctx->refcount > 0);
+ ctx->refcount++;
+}
+
+static inline void
+decref_callback_context(callback_context *ctx)
+{
+ assert(PyGILState_Check());
+ assert(ctx != NULL);
+ assert(ctx->refcount > 0);
+ ctx->refcount--;
+ if (ctx->refcount == 0) {
+ free_callback_context(ctx);
+ }
+}
+
static void
set_callback_context(callback_context **ctx_pp, callback_context *ctx)
{
@@ -1124,7 +1151,7 @@ set_callback_context(callback_context **ctx_pp, callback_context *ctx)
callback_context *tmp = *ctx_pp;
*ctx_pp = ctx;
if (tmp != NULL) {
- free_callback_context(tmp);
+ decref_callback_context(tmp);
}
}
@@ -1135,7 +1162,7 @@ destructor_callback(void *ctx)
// This function may be called without the GIL held, so we need to
// ensure that we destroy 'ctx' with the GIL held.
PyGILState_STATE gstate = PyGILState_Ensure();
- free_callback_context((callback_context *)ctx);
+ decref_callback_context((callback_context *)ctx);
PyGILState_Release(gstate);
}
}
@@ -1180,7 +1207,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
func_callback,
NULL,
NULL,
- &destructor_callback); // will decref func
+ &destructor_callback); // will free 'ctx'
if (rc != SQLITE_OK) {
/* Workaround for SQLite bug: no error code or string is available here */
@@ -1204,7 +1231,7 @@ inverse_callback(sqlite3_context *context, int argc, sqlite3_value **params)
PyGILState_STATE gilstate = PyGILState_Ensure();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
int size = sizeof(PyObject *);
PyObject **cls = (PyObject **)sqlite3_aggregate_context(context, size);
@@ -1236,6 +1263,7 @@ inverse_callback(sqlite3_context *context, int argc, sqlite3_value **params)
Py_DECREF(res);
exit:
+ decref_callback_context(ctx);
Py_XDECREF(method);
PyGILState_Release(gilstate);
}
@@ -1252,7 +1280,7 @@ value_callback(sqlite3_context *context)
PyGILState_STATE gilstate = PyGILState_Ensure();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
int size = sizeof(PyObject *);
PyObject **cls = (PyObject **)sqlite3_aggregate_context(context, size);
@@ -1260,6 +1288,8 @@ value_callback(sqlite3_context *context)
assert(*cls != NULL);
PyObject *res = PyObject_CallMethodNoArgs(*cls, ctx->state->str_value);
+ decref_callback_context(ctx);
+
if (res == NULL) {
int attr_err = PyErr_ExceptionMatches(PyExc_AttributeError);
set_sqlite_error(context, attr_err
@@ -1377,7 +1407,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
0,
&step_callback,
&final_callback,
- &destructor_callback); // will decref func
+ &destructor_callback); // will free 'ctx'
if (rc != SQLITE_OK) {
/* Workaround for SQLite bug: no error code or string is available here */
PyErr_SetString(self->OperationalError, "Error creating aggregate");
@@ -1387,7 +1417,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
}
static int
-authorizer_callback(void *ctx, int action, const char *arg1,
+authorizer_callback(void *ctx_vp, int action, const char *arg1,
const char *arg2 , const char *dbname,
const char *access_attempt_source)
{
@@ -1396,8 +1426,9 @@ authorizer_callback(void *ctx, int action, const char *arg1,
PyObject *ret;
int rc = SQLITE_DENY;
- assert(ctx != NULL);
- PyObject *callable = ((callback_context *)ctx)->callable;
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+ PyObject *callable = ctx->callable;
ret = PyObject_CallFunction(callable, "issss", action, arg1, arg2, dbname,
access_attempt_source);
@@ -1419,21 +1450,23 @@ authorizer_callback(void *ctx, int action, const char *arg1,
Py_DECREF(ret);
}
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return rc;
}
static int
-progress_callback(void *ctx)
+progress_callback(void *ctx_vp)
{
PyGILState_STATE gilstate = PyGILState_Ensure();
int rc;
PyObject *ret;
- assert(ctx != NULL);
- PyObject *callable = ((callback_context *)ctx)->callable;
- ret = PyObject_CallNoArgs(callable);
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+
+ ret = PyObject_CallNoArgs(ctx->callable);
if (!ret) {
/* abort query if error occurred */
rc = -1;
@@ -1446,6 +1479,7 @@ progress_callback(void *ctx)
print_or_clear_traceback(ctx);
}
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return rc;
}
@@ -1457,7 +1491,7 @@ progress_callback(void *ctx)
* to ensure future compatibility.
*/
static int
-trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
+trace_callback(unsigned int type, void *ctx_vp, void *stmt, void *sql)
{
if (type != SQLITE_TRACE_STMT) {
return 0;
@@ -1465,8 +1499,9 @@ trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
PyGILState_STATE gilstate = PyGILState_Ensure();
- assert(ctx != NULL);
- pysqlite_state *state = ((callback_context *)ctx)->state;
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+ pysqlite_state *state = ctx->state;
assert(state != NULL);
PyObject *py_statement = NULL;
@@ -1480,7 +1515,7 @@ trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
PyErr_SetString(state->DataError,
"Expanded SQL string exceeds the maximum string length");
- print_or_clear_traceback((callback_context *)ctx);
+ print_or_clear_traceback(ctx);
// Fall back to unexpanded sql
py_statement = PyUnicode_FromString((const char *)sql);
@@ -1490,16 +1525,16 @@ trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
sqlite3_free((void *)expanded_sql);
}
if (py_statement) {
- PyObject *callable = ((callback_context *)ctx)->callable;
- PyObject *ret = PyObject_CallOneArg(callable, py_statement);
+ PyObject *ret = PyObject_CallOneArg(ctx->callable, py_statement);
Py_DECREF(py_statement);
Py_XDECREF(ret);
}
if (PyErr_Occurred()) {
- print_or_clear_traceback((callback_context *)ctx);
+ print_or_clear_traceback(ctx);
}
exit:
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return 0;
}
@@ -1914,6 +1949,8 @@ collation_callback(void *context, int text1_length, const void *text1_data,
PyObject* retval = NULL;
long longval;
int result = 0;
+ callback_context *ctx = (callback_context *)context;
+ incref_callback_context(ctx);
/* This callback may be executed multiple times per sqlite3_step(). Bail if
* the previous call failed */
@@ -1930,8 +1967,6 @@ collation_callback(void *context, int text1_length, const void *text1_data,
goto finally;
}
- callback_context *ctx = (callback_context *)context;
- assert(ctx != NULL);
PyObject *args[] = { NULL, string1, string2 }; // Borrowed refs.
size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
retval = PyObject_Vectorcall(ctx->callable, args + 1, nargsf, NULL);
@@ -1953,6 +1988,7 @@ collation_callback(void *context, int text1_length, const void *text1_data,
}
finally:
+ decref_callback_context(ctx);
Py_XDECREF(string1);
Py_XDECREF(string2);
Py_XDECREF(retval);
diff --git a/contrib/tools/python3/Modules/_sqlite/connection.h b/contrib/tools/python3/Modules/_sqlite/connection.h
index 7a748ee3ea0..703396a0c8d 100644
--- a/contrib/tools/python3/Modules/_sqlite/connection.h
+++ b/contrib/tools/python3/Modules/_sqlite/connection.h
@@ -36,6 +36,7 @@ typedef struct _callback_context
PyObject *callable;
PyObject *module;
pysqlite_state *state;
+ Py_ssize_t refcount;
} callback_context;
enum autocommit_mode {
diff --git a/contrib/tools/python3/Modules/_sqlite/ya.make b/contrib/tools/python3/Modules/_sqlite/ya.make
index eef017d69e9..52461066edb 100644
--- a/contrib/tools/python3/Modules/_sqlite/ya.make
+++ b/contrib/tools/python3/Modules/_sqlite/ya.make
@@ -2,9 +2,9 @@
PY3_LIBRARY()
-VERSION(3.13.11)
+VERSION(3.13.12)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.11.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.12.tar.gz)
LICENSE(Python-2.0)
diff --git a/contrib/tools/python3/Modules/_struct.c b/contrib/tools/python3/Modules/_struct.c
index a9f8fa4bbde..016a1d3cf21 100644
--- a/contrib/tools/python3/Modules/_struct.c
+++ b/contrib/tools/python3/Modules/_struct.c
@@ -1498,8 +1498,6 @@ prepare_s(PyStructObject *self)
return -1;
}
- self->s_size = size;
- self->s_len = len;
codes = PyMem_Malloc((ncodes + 1) * sizeof(formatcode));
if (codes == NULL) {
PyErr_NoMemory();
@@ -1509,6 +1507,8 @@ prepare_s(PyStructObject *self)
if (self->s_codes != NULL)
PyMem_Free(self->s_codes);
self->s_codes = codes;
+ self->s_size = size;
+ self->s_len = len;
s = fmt;
size = 0;
@@ -1695,6 +1695,14 @@ fail:
return NULL;
}
+#define ENSURE_STRUCT_IS_READY(self) \
+ do { \
+ if (!(self)->s_codes) { \
+ PyErr_SetString(PyExc_RuntimeError, \
+ "Struct object is not initialized"); \
+ return NULL; \
+ } \
+ } while (0);
/*[clinic input]
Struct.unpack
@@ -1715,7 +1723,7 @@ Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer)
/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (buffer->len != self->s_size) {
PyErr_Format(state->StructError,
"unpack requires a buffer of %zd bytes",
@@ -1747,7 +1755,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer,
/*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (offset < 0) {
if (offset + self->s_size > 0) {
@@ -1890,8 +1898,7 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer)
{
_structmodulestate *state = get_struct_state_structinst(self);
unpackiterobject *iter;
-
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (self->s_size == 0) {
PyErr_Format(state->StructError,
@@ -2032,8 +2039,8 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
/* Validate arguments. */
soself = (PyStructObject *)self;
+ ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
- assert(soself->s_codes != NULL);
if (nargs != soself->s_len)
{
PyErr_Format(state->StructError,
@@ -2077,8 +2084,8 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
/* Validate arguments. +1 is for the first arg as buffer. */
soself = (PyStructObject *)self;
+ ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
- assert(soself->s_codes != NULL);
if (nargs != (soself->s_len + 2))
{
if (nargs == 0) {
@@ -2164,6 +2171,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
static PyObject *
s_get_format(PyStructObject *self, void *unused)
{
+ ENSURE_STRUCT_IS_READY(self);
return PyUnicode_FromStringAndSize(PyBytes_AS_STRING(self->s_format),
PyBytes_GET_SIZE(self->s_format));
}
@@ -2474,8 +2482,7 @@ The optional first format char indicates byte order, size and alignment:\n\
The remaining chars indicate types of args and must match exactly;\n\
these can be preceded by a decimal repeat count:\n\
x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
- ?: _Bool (requires C99; if not available, char is used instead)\n\
- h:short; H:unsigned short; i:int; I:unsigned int;\n\
+ ?:_Bool; h:short; H:unsigned short; i:int; I:unsigned int;\n\
l:long; L:unsigned long; f:float; d:double; e:half-float.\n\
Special cases (preceding decimal count indicates length):\n\
s:string (array of char); p: pascal string (with count byte).\n\
diff --git a/contrib/tools/python3/Modules/_zoneinfo.c b/contrib/tools/python3/Modules/_zoneinfo.c
index 63643b7bfc7..2cb48d91494 100644
--- a/contrib/tools/python3/Modules/_zoneinfo.c
+++ b/contrib/tools/python3/Modules/_zoneinfo.c
@@ -287,16 +287,11 @@ static PyObject *
get_weak_cache(zoneinfo_state *state, PyTypeObject *type)
{
if (type == state->ZoneInfoType) {
+ Py_INCREF(state->ZONEINFO_WEAK_CACHE);
return state->ZONEINFO_WEAK_CACHE;
}
else {
- PyObject *cache =
- PyObject_GetAttrString((PyObject *)type, "_weak_cache");
- // We are assuming that the type lives at least as long as the function
- // that calls get_weak_cache, and that it holds a reference to the
- // cache, so we'll return a "borrowed reference".
- Py_XDECREF(cache);
- return cache;
+ return PyObject_GetAttrString((PyObject *)type, "_weak_cache");
}
}
@@ -323,6 +318,7 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
PyObject *weak_cache = get_weak_cache(state, type);
instance = PyObject_CallMethod(weak_cache, "get", "O", key, Py_None);
if (instance == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
@@ -330,6 +326,7 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
Py_DECREF(instance);
PyObject *tmp = zoneinfo_new_instance(state, type, key);
if (tmp == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
@@ -337,12 +334,14 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
PyObject_CallMethod(weak_cache, "setdefault", "OO", key, tmp);
Py_DECREF(tmp);
if (instance == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
((PyZoneInfo_ZoneInfo *)instance)->source = SOURCE_CACHE;
}
update_strong_cache(state, type, key, instance);
+ Py_DECREF(weak_cache);
return instance;
}
@@ -504,12 +503,14 @@ zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyTypeObject *cls,
PyObject *item = NULL;
PyObject *pop = PyUnicode_FromString("pop");
if (pop == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
PyObject *iter = PyObject_GetIter(only_keys);
if (iter == NULL) {
Py_DECREF(pop);
+ Py_DECREF(weak_cache);
return NULL;
}
@@ -534,6 +535,7 @@ zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyTypeObject *cls,
Py_DECREF(pop);
}
+ Py_DECREF(weak_cache);
if (PyErr_Occurred()) {
return NULL;
}
diff --git a/contrib/tools/python3/Modules/arraymodule.c b/contrib/tools/python3/Modules/arraymodule.c
index 1f800af6ad5..4c7cc4d47c0 100644
--- a/contrib/tools/python3/Modules/arraymodule.c
+++ b/contrib/tools/python3/Modules/arraymodule.c
@@ -202,6 +202,33 @@ Note that the basic Get and Set functions do NOT check that the index is
in bounds; that's the responsibility of the caller.
****************************************************************************/
+/* Macro to check array buffer validity and bounds after calling
+ user-defined methods (like __index__ or __float__) that might modify
+ the array during the call.
+*/
+#define CHECK_ARRAY_BOUNDS(OP, IDX) \
+ do { \
+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
+ (IDX) >= Py_SIZE((OP)))) { \
+ PyErr_SetString(PyExc_IndexError, \
+ "array assignment index out of range"); \
+ return -1; \
+ } \
+ } while (0)
+
+#define CHECK_ARRAY_BOUNDS_WITH_CLEANUP(OP, IDX, VAL, CLEANUP) \
+ do { \
+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
+ (IDX) >= Py_SIZE((OP)))) { \
+ PyErr_SetString(PyExc_IndexError, \
+ "array assignment index out of range"); \
+ if (CLEANUP) { \
+ Py_DECREF(VAL); \
+ } \
+ return -1; \
+ } \
+ } while (0)
+
static PyObject *
b_getitem(arrayobject *ap, Py_ssize_t i)
{
@@ -218,7 +245,10 @@ b_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
the overflow checking */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
- else if (x < -128) {
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
+ if (x < -128) {
PyErr_SetString(PyExc_OverflowError,
"signed char is less than minimum");
return -1;
@@ -247,6 +277,9 @@ BB_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'B' == unsigned char, maps to PyArg_Parse's 'b' formatter */
if (!PyArg_Parse(v, "b;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((unsigned char *)ap->ob_item)[i] = x;
return 0;
@@ -323,6 +356,9 @@ h_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'h' == signed short, maps to PyArg_Parse's 'h' formatter */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((short *)ap->ob_item)[i] = x;
return 0;
@@ -352,6 +388,9 @@ HH_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
"unsigned short is greater than maximum");
return -1;
}
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((short *)ap->ob_item)[i] = (short)x;
return 0;
@@ -370,6 +409,9 @@ i_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'i' == signed int, maps to PyArg_Parse's 'i' formatter */
if (!PyArg_Parse(v, "i;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((int *)ap->ob_item)[i] = x;
return 0;
@@ -410,6 +452,9 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned int *)ap->ob_item)[i] = (unsigned int)x;
@@ -431,6 +476,9 @@ l_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
long x;
if (!PyArg_Parse(v, "l;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((long *)ap->ob_item)[i] = x;
return 0;
@@ -462,6 +510,9 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned long *)ap->ob_item)[i] = x;
@@ -483,6 +534,9 @@ q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
long long x;
if (!PyArg_Parse(v, "L;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((long long *)ap->ob_item)[i] = x;
return 0;
@@ -515,6 +569,9 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned long long *)ap->ob_item)[i] = x;
@@ -536,6 +593,9 @@ f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
float x;
if (!PyArg_Parse(v, "f;array item must be float", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((float *)ap->ob_item)[i] = x;
return 0;
@@ -553,6 +613,9 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
double x;
if (!PyArg_Parse(v, "d;array item must be float", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((double *)ap->ob_item)[i] = x;
return 0;
diff --git a/contrib/tools/python3/Modules/atexitmodule.c b/contrib/tools/python3/Modules/atexitmodule.c
index c009235b7a3..23fcc1b9d35 100644
--- a/contrib/tools/python3/Modules/atexitmodule.c
+++ b/contrib/tools/python3/Modules/atexitmodule.c
@@ -57,6 +57,9 @@ static void
atexit_delete_cb(struct atexit_state *state, int i)
{
atexit_py_callback *cb = state->callbacks[i];
+ if (cb == NULL) {
+ return;
+ }
state->callbacks[i] = NULL;
Py_DECREF(cb->func);
@@ -287,7 +290,9 @@ atexit_unregister(PyObject *module, PyObject *func)
continue;
}
- int eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
+ PyObject *to_compare = Py_NewRef(cb->func);
+ int eq = PyObject_RichCompareBool(to_compare, func, Py_EQ);
+ Py_DECREF(to_compare);
if (eq < 0) {
return NULL;
}
diff --git a/contrib/tools/python3/Modules/overlapped.c b/contrib/tools/python3/Modules/overlapped.c
index 77ee70ae133..567593e05c4 100644
--- a/contrib/tools/python3/Modules/overlapped.c
+++ b/contrib/tools/python3/Modules/overlapped.c
@@ -1794,7 +1794,7 @@ _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle,
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
@@ -1868,7 +1868,7 @@ _overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject *self,
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
@@ -1935,7 +1935,7 @@ _overlapped_Overlapped_WSARecvFromInto_impl(OverlappedObject *self,
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
diff --git a/contrib/tools/python3/Modules/posixmodule.c b/contrib/tools/python3/Modules/posixmodule.c
index 698e707b62d..24df9546064 100644
--- a/contrib/tools/python3/Modules/posixmodule.c
+++ b/contrib/tools/python3/Modules/posixmodule.c
@@ -1534,7 +1534,7 @@ static int
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
int follow_symlinks)
{
- if ((fd > 0) && (!follow_symlinks)) {
+ if ((fd >= 0) && (!follow_symlinks)) {
PyErr_Format(PyExc_ValueError,
"%s: cannot use fd and follow_symlinks together",
function_name);
@@ -1699,7 +1699,7 @@ convertenviron(void)
#ifdef MS_WINDOWS
k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
#else
- k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
+ k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
#endif
if (k == NULL) {
Py_DECREF(d);
@@ -6741,8 +6741,8 @@ static EXECV_CHAR**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
{
Py_ssize_t i, pos, envc;
- PyObject *keys=NULL, *vals=NULL;
- PyObject *key2, *val2, *keyval;
+ PyObject *keys = NULL, *vals = NULL;
+ PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
EXECV_CHAR **envlist;
i = PyMapping_Size(env);
@@ -6767,20 +6767,22 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
}
for (pos = 0; pos < i; pos++) {
- PyObject *key = PyList_GetItem(keys, pos); // Borrowed ref.
+ // The 'key' and 'val' must be strong references because of
+ // possible side-effects by PyUnicode_FS{Converter,Decoder}().
+ key = PyList_GetItemRef(keys, pos);
if (key == NULL) {
goto error;
}
- PyObject *val = PyList_GetItem(vals, pos); // Borrowed ref.
+ val = PyList_GetItemRef(vals, pos);
if (val == NULL) {
goto error;
}
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
- if (!PyUnicode_FSDecoder(key, &key2))
+ if (!PyUnicode_FSDecoder(key, &key2)) {
goto error;
+ }
if (!PyUnicode_FSDecoder(val, &val2)) {
- Py_DECREF(key2);
goto error;
}
/* Search from index 1 because on Windows starting '=' is allowed for
@@ -6789,39 +6791,38 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
{
PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
- Py_DECREF(key2);
- Py_DECREF(val2);
goto error;
}
- keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
+ PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
#else
- if (!PyUnicode_FSConverter(key, &key2))
+ if (!PyUnicode_FSConverter(key, &key2)) {
goto error;
+ }
if (!PyUnicode_FSConverter(val, &val2)) {
- Py_DECREF(key2);
goto error;
}
if (PyBytes_GET_SIZE(key2) == 0 ||
strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
{
PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
- Py_DECREF(key2);
- Py_DECREF(val2);
goto error;
}
- keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
- PyBytes_AS_STRING(val2));
+ PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
+ PyBytes_AS_STRING(val2));
#endif
- Py_DECREF(key2);
- Py_DECREF(val2);
- if (!keyval)
+ if (!keyval) {
goto error;
+ }
if (!fsconvert_strdup(keyval, &envlist[envc++])) {
Py_DECREF(keyval);
goto error;
}
+ Py_CLEAR(key);
+ Py_CLEAR(val);
+ Py_CLEAR(key2);
+ Py_CLEAR(val2);
Py_DECREF(keyval);
}
Py_DECREF(vals);
@@ -6832,6 +6833,10 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
return envlist;
error:
+ Py_XDECREF(key);
+ Py_XDECREF(val);
+ Py_XDECREF(key2);
+ Py_XDECREF(val2);
Py_XDECREF(keys);
Py_XDECREF(vals);
free_string_array(envlist, envc);
@@ -7353,7 +7358,7 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
if (argc < 1) {
PyErr_Format(PyExc_ValueError,
"%s: argv must not be empty", func_name);
- return NULL;
+ goto exit;
}
if (!PyMapping_Check(env) && env != Py_None) {
diff --git a/contrib/tools/python3/Modules/socketmodule.c b/contrib/tools/python3/Modules/socketmodule.c
index edc79c9d3b8..6df7401133a 100644
--- a/contrib/tools/python3/Modules/socketmodule.c
+++ b/contrib/tools/python3/Modules/socketmodule.c
@@ -2649,6 +2649,11 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
/* RDS sockets use sockaddr_in: fall-through */
#endif /* AF_RDS */
+#ifdef AF_DIVERT
+ case AF_DIVERT:
+ /* FreeBSD divert(4) sockets use sockaddr_in: fall-through */
+#endif /* AF_DIVERT */
+
case AF_INET:
{
*len_ret = sizeof (struct sockaddr_in);
diff --git a/contrib/tools/python3/Objects/bytearrayobject.c b/contrib/tools/python3/Objects/bytearrayobject.c
index 5382b1bdfa5..feea0aef276 100644
--- a/contrib/tools/python3/Objects/bytearrayobject.c
+++ b/contrib/tools/python3/Objects/bytearrayobject.c
@@ -64,6 +64,24 @@ bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view)
assert(obj->ob_exports >= 0);
}
+typedef PyObject* (*_ba_bytes_op)(const char *buf, Py_ssize_t len,
+ PyObject *sub, Py_ssize_t start,
+ Py_ssize_t end);
+
+static PyObject *
+_bytearray_with_buffer(PyByteArrayObject *self, _ba_bytes_op op, PyObject *sub,
+ Py_ssize_t start, Py_ssize_t end)
+{
+ PyObject *res;
+
+ /* Increase exports to prevent bytearray storage from changing during op. */
+ self->ob_exports++;
+ res = op(PyByteArray_AS_STRING(self), Py_SIZE(self), sub, start, end);
+ self->ob_exports--;
+
+ return res;
+}
+
static int
_canresize(PyByteArrayObject *self)
{
@@ -1146,8 +1164,7 @@ bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start,
Py_ssize_t end)
/*[clinic end generated code: output=413e1cab2ae87da0 input=793dfad803e2952f]*/
{
- return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
- sub, start, end);
+ return _bytearray_with_buffer(self, _Py_bytes_find, sub, start, end);
}
/*[clinic input]
@@ -1161,8 +1178,7 @@ bytearray_count_impl(PyByteArrayObject *self, PyObject *sub,
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=a21ee2692e4f1233 input=4deb529db38deda8]*/
{
- return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
- sub, start, end);
+ return _bytearray_with_buffer(self, _Py_bytes_count, sub, start, end);
}
/*[clinic input]
@@ -1207,8 +1223,7 @@ bytearray_index_impl(PyByteArrayObject *self, PyObject *sub,
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=067a1e78efc672a7 input=8cbaf6836dbd2a9a]*/
{
- return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
- sub, start, end);
+ return _bytearray_with_buffer(self, _Py_bytes_index, sub, start, end);
}
/*[clinic input]
@@ -1224,8 +1239,7 @@ bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub,
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=51bf886f932b283c input=eaa107468a158423]*/
{
- return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
- sub, start, end);
+ return _bytearray_with_buffer(self, _Py_bytes_rfind, sub, start, end);
}
/*[clinic input]
@@ -1241,14 +1255,22 @@ bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub,
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=38e1cf66bafb08b9 input=81cf49d0af4d5bd0]*/
{
- return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
- sub, start, end);
+ return _bytearray_with_buffer(self, _Py_bytes_rindex, sub, start, end);
}
static int
bytearray_contains(PyObject *self, PyObject *arg)
{
- return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg);
+ int ret = -1;
+ PyByteArrayObject *ba = _PyByteArray_CAST(self);
+
+ /* Increase exports to prevent bytearray storage from changing during _Py_bytes_contains(). */
+ ba->ob_exports++;
+ ret = _Py_bytes_contains(PyByteArray_AS_STRING(ba),
+ PyByteArray_GET_SIZE(self),
+ arg);
+ ba->ob_exports--;
+ return ret;
}
/*[clinic input]
@@ -1271,8 +1293,7 @@ bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj,
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=a3d9b6d44d3662a6 input=76385e0b376b45c1]*/
{
- return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
- subobj, start, end);
+ return _bytearray_with_buffer(self, _Py_bytes_startswith, subobj, start, end);
}
/*[clinic input]
@@ -1295,8 +1316,7 @@ bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj,
Py_ssize_t start, Py_ssize_t end)
/*[clinic end generated code: output=e75ea8c227954caa input=9b8baa879aa3d74b]*/
{
- return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
- subobj, start, end);
+ return _bytearray_with_buffer(self, _Py_bytes_endswith, subobj, start, end);
}
/*[clinic input]
@@ -1539,26 +1559,32 @@ bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
Py_ssize_t maxsplit)
/*[clinic end generated code: output=833e2cf385d9a04d input=24f82669f41bf523]*/
{
- Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
- const char *s = PyByteArray_AS_STRING(self), *sub;
- PyObject *list;
- Py_buffer vsub;
+ PyObject *list = NULL;
+
+ /* Increase exports to prevent bytearray storage from changing during _Py_bytes_contains(). */
+ self->ob_exports++;
+ const char *sbuf = PyByteArray_AS_STRING(self);
+ Py_ssize_t slen = PyByteArray_GET_SIZE((PyObject *)self);
if (maxsplit < 0)
maxsplit = PY_SSIZE_T_MAX;
- if (sep == Py_None)
- return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
+ if (sep == Py_None) {
+ list = stringlib_split_whitespace((PyObject*)self, sbuf, slen, maxsplit);
+ goto done;
+ }
- if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
- return NULL;
- sub = vsub.buf;
- n = vsub.len;
+ Py_buffer vsub;
+ if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) {
+ goto done;
+ }
- list = stringlib_split(
- (PyObject*) self, s, len, sub, n, maxsplit
- );
+ list = stringlib_split((PyObject*)self, sbuf, slen,
+ (const char *)vsub.buf, vsub.len, maxsplit);
PyBuffer_Release(&vsub);
+
+done:
+ self->ob_exports--;
return list;
}
@@ -1650,26 +1676,32 @@ bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
Py_ssize_t maxsplit)
/*[clinic end generated code: output=a55e0b5a03cb6190 input=a68286e4dd692ffe]*/
{
- Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
- const char *s = PyByteArray_AS_STRING(self), *sub;
- PyObject *list;
- Py_buffer vsub;
+ PyObject *list = NULL;
+
+ /* Increase exports to prevent bytearray storage from changing during _Py_bytes_contains(). */
+ self->ob_exports++;
+ const char *sbuf = PyByteArray_AS_STRING(self);
+ Py_ssize_t slen = PyByteArray_GET_SIZE((PyObject *)self);
if (maxsplit < 0)
maxsplit = PY_SSIZE_T_MAX;
- if (sep == Py_None)
- return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
+ if (sep == Py_None) {
+ list = stringlib_rsplit_whitespace((PyObject*)self, sbuf, slen, maxsplit);
+ goto done;
+ }
- if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
- return NULL;
- sub = vsub.buf;
- n = vsub.len;
+ Py_buffer vsub;
+ if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) {
+ goto done;
+ }
- list = stringlib_rsplit(
- (PyObject*) self, s, len, sub, n, maxsplit
- );
+ list = stringlib_rsplit((PyObject*)self, sbuf, slen,
+ (const char *)vsub.buf, vsub.len, maxsplit);
PyBuffer_Release(&vsub);
+
+done:
+ self->ob_exports--;
return list;
}
@@ -1839,7 +1871,6 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
Py_DECREF(bytearray_obj);
return NULL;
}
- buf[len++] = value;
Py_DECREF(item);
if (len >= buf_size) {
@@ -1849,7 +1880,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
Py_DECREF(bytearray_obj);
return PyErr_NoMemory();
}
- addition = len >> 1;
+ addition = len ? len >> 1 : 1;
if (addition > PY_SSIZE_T_MAX - len - 1)
buf_size = PY_SSIZE_T_MAX;
else
@@ -1863,6 +1894,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
have invalidated it. */
buf = PyByteArray_AS_STRING(bytearray_obj);
}
+ buf[len++] = value;
}
Py_DECREF(it);
@@ -2192,7 +2224,13 @@ bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep)
{
char* argbuf = PyByteArray_AS_STRING(self);
Py_ssize_t arglen = PyByteArray_GET_SIZE(self);
- return _Py_strhex_with_sep(argbuf, arglen, sep, bytes_per_sep);
+ // Prevent 'self' from being freed if computing len(sep) mutates 'self'
+ // in _Py_strhex_with_sep().
+ // See: https://github.com/python/cpython/issues/143195.
+ self->ob_exports++;
+ PyObject *res = _Py_strhex_with_sep(argbuf, arglen, sep, bytes_per_sep);
+ self->ob_exports--;
+ return res;
}
static PyObject *
@@ -2363,7 +2401,15 @@ bytearray_mod(PyObject *v, PyObject *w)
{
if (!PyByteArray_Check(v))
Py_RETURN_NOTIMPLEMENTED;
- return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
+
+ PyByteArrayObject *self = _PyByteArray_CAST(v);
+ /* Increase exports to prevent bytearray storage from changing during op. */
+ self->ob_exports++;
+ PyObject *res = _PyBytes_FormatEx(
+ PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1
+ );
+ self->ob_exports--;
+ return res;
}
static PyNumberMethods bytearray_as_number = {
diff --git a/contrib/tools/python3/Objects/call.c b/contrib/tools/python3/Objects/call.c
index b1610dababd..6e331a43899 100644
--- a/contrib/tools/python3/Objects/call.c
+++ b/contrib/tools/python3/Objects/call.c
@@ -726,6 +726,7 @@ _PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name,
PyObject * _PyObject_CallMethodFormat(PyThreadState *tstate, PyObject *callable,
const char *format, ...)
{
+ assert(callable != NULL);
va_list va;
va_start(va, format);
PyObject *retval = callmethod(tstate, callable, format, va);
diff --git a/contrib/tools/python3/Objects/dictobject.c b/contrib/tools/python3/Objects/dictobject.c
index c987af31c45..3e0537c1817 100644
--- a/contrib/tools/python3/Objects/dictobject.c
+++ b/contrib/tools/python3/Objects/dictobject.c
@@ -1832,7 +1832,7 @@ static int
insertdict(PyInterpreterState *interp, PyDictObject *mp,
PyObject *key, Py_hash_t hash, PyObject *value)
{
- PyObject *old_value;
+ PyObject *old_value = NULL;
Py_ssize_t ix;
ASSERT_DICT_LOCKED(mp);
@@ -1856,11 +1856,14 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
}
- if (ix == DKIX_EMPTY) {
+ if (old_value == NULL) {
// insert_combined_dict() will convert from non DICT_KEYS_GENERAL table
// into DICT_KEYS_GENERAL table if key is not Unicode.
// We don't convert it before _Py_dict_lookup because non-Unicode key
// may change generic table into Unicode table.
+ //
+ // NOTE: ix may not be DKIX_EMPTY because split table may have key
+ // without value.
if (insert_combined_dict(interp, mp, hash, key, value) < 0) {
goto Fail;
}
diff --git a/contrib/tools/python3/Objects/exceptions.c b/contrib/tools/python3/Objects/exceptions.c
index a1fda3c1fd1..db2774d3d6a 100644
--- a/contrib/tools/python3/Objects/exceptions.c
+++ b/contrib/tools/python3/Objects/exceptions.c
@@ -531,13 +531,13 @@ PyTypeObject _PyExc_ ## EXCNAME = { \
#define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCNEW, \
EXCMETHODS, EXCMEMBERS, EXCGETSET, \
- EXCSTR, EXCDOC) \
+ EXCSTR, EXCREPR, EXCDOC) \
static PyTypeObject _PyExc_ ## EXCNAME = { \
PyVarObject_HEAD_INIT(NULL, 0) \
# EXCNAME, \
sizeof(Py ## EXCSTORE ## Object), 0, \
- (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- (reprfunc)EXCSTR, 0, 0, 0, \
+ (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, (reprfunc)EXCREPR, 0, 0, 0, \
+ 0, 0, (reprfunc)EXCSTR, 0, 0, 0, \
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
(inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \
@@ -619,7 +619,7 @@ StopIteration_traverse(PyStopIterationObject *self, visitproc visit, void *arg)
}
ComplexExtendsException(PyExc_Exception, StopIteration, StopIteration,
- 0, 0, StopIteration_members, 0, 0,
+ 0, 0, StopIteration_members, 0, 0, 0,
"Signal the end from iterator.__next__().");
@@ -682,7 +682,7 @@ static PyMemberDef SystemExit_members[] = {
};
ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit,
- 0, 0, SystemExit_members, 0, 0,
+ 0, 0, SystemExit_members, 0, 0, 0,
"Request to exit from the interpreter.");
/*
@@ -707,6 +707,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject *message = NULL;
PyObject *exceptions = NULL;
+ PyObject *exceptions_str = NULL;
if (!PyArg_ParseTuple(args,
"UO:BaseExceptionGroup.__new__",
@@ -722,6 +723,18 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
+ /* Save initial exceptions sequence as a string in case sequence is mutated */
+ if (!PyList_Check(exceptions) && !PyTuple_Check(exceptions)) {
+ exceptions_str = PyObject_Repr(exceptions);
+ if (exceptions_str == NULL) {
+ /* We don't hold a reference to exceptions, so clear it before
+ * attempting a decref in the cleanup.
+ */
+ exceptions = NULL;
+ goto error;
+ }
+ }
+
exceptions = PySequence_Tuple(exceptions);
if (!exceptions) {
return NULL;
@@ -805,9 +818,11 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->msg = Py_NewRef(message);
self->excs = exceptions;
+ self->excs_str = exceptions_str;
return (PyObject*)self;
error:
- Py_DECREF(exceptions);
+ Py_XDECREF(exceptions);
+ Py_XDECREF(exceptions_str);
return NULL;
}
@@ -846,6 +861,7 @@ BaseExceptionGroup_clear(PyBaseExceptionGroupObject *self)
{
Py_CLEAR(self->msg);
Py_CLEAR(self->excs);
+ Py_CLEAR(self->excs_str);
return BaseException_clear((PyBaseExceptionObject *)self);
}
@@ -863,6 +879,7 @@ BaseExceptionGroup_traverse(PyBaseExceptionGroupObject *self,
{
Py_VISIT(self->msg);
Py_VISIT(self->excs);
+ Py_VISIT(self->excs_str);
return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
}
@@ -880,6 +897,53 @@ BaseExceptionGroup_str(PyBaseExceptionGroupObject *self)
}
static PyObject *
+BaseExceptionGroup_repr(PyBaseExceptionGroupObject *self)
+{
+ assert(self->msg);
+
+ PyObject *exceptions_str = NULL;
+
+ /* Use the saved exceptions string for custom sequences. */
+ if (self->excs_str) {
+ exceptions_str = Py_NewRef(self->excs_str);
+ }
+ else {
+ assert(self->excs);
+
+ /* Older versions delegated to BaseException, inserting the current
+ * value of self.args[1]; but this can be mutable and go out-of-sync
+ * with self.exceptions. Instead, use self.exceptions for accuracy,
+ * making it look like self.args[1] for backwards compatibility. */
+ if (PyList_Check(PyTuple_GET_ITEM(self->args, 1))) {
+ PyObject *exceptions_list = PySequence_List(self->excs);
+ if (!exceptions_list) {
+ return NULL;
+ }
+
+ exceptions_str = PyObject_Repr(exceptions_list);
+ Py_DECREF(exceptions_list);
+ }
+ else {
+ exceptions_str = PyObject_Repr(self->excs);
+ }
+
+ if (!exceptions_str) {
+ return NULL;
+ }
+ }
+
+ assert(exceptions_str != NULL);
+
+ const char *name = _PyType_Name(Py_TYPE(self));
+ PyObject *repr = PyUnicode_FromFormat(
+ "%s(%R, %U)", name,
+ self->msg, exceptions_str);
+
+ Py_DECREF(exceptions_str);
+ return repr;
+}
+
+static PyObject *
BaseExceptionGroup_derive(PyObject *self_, PyObject *excs)
{
PyBaseExceptionGroupObject *self = _PyBaseExceptionGroupObject_cast(self_);
@@ -1487,7 +1551,7 @@ static PyMethodDef BaseExceptionGroup_methods[] = {
ComplexExtendsException(PyExc_BaseException, BaseExceptionGroup,
BaseExceptionGroup, BaseExceptionGroup_new /* new */,
BaseExceptionGroup_methods, BaseExceptionGroup_members,
- 0 /* getset */, BaseExceptionGroup_str,
+ 0 /* getset */, BaseExceptionGroup_str, BaseExceptionGroup_repr,
"A combination of multiple unrelated exceptions.");
/*
@@ -1664,7 +1728,7 @@ static PyMethodDef ImportError_methods[] = {
ComplexExtendsException(PyExc_Exception, ImportError,
ImportError, 0 /* new */,
ImportError_methods, ImportError_members,
- 0 /* getset */, ImportError_str,
+ 0 /* getset */, ImportError_str, 0,
"Import can't find module, or can't find name in "
"module.");
@@ -2124,7 +2188,7 @@ static PyGetSetDef OSError_getset[] = {
ComplexExtendsException(PyExc_Exception, OSError,
OSError, OSError_new,
OSError_methods, OSError_members, OSError_getset,
- OSError_str,
+ OSError_str, 0,
"Base class for I/O related errors.");
@@ -2255,7 +2319,7 @@ static PyMethodDef NameError_methods[] = {
ComplexExtendsException(PyExc_Exception, NameError,
NameError, 0,
NameError_methods, NameError_members,
- 0, BaseException_str, "Name not found globally.");
+ 0, BaseException_str, 0, "Name not found globally.");
/*
* UnboundLocalError extends NameError
@@ -2377,7 +2441,7 @@ static PyMethodDef AttributeError_methods[] = {
ComplexExtendsException(PyExc_Exception, AttributeError,
AttributeError, 0,
AttributeError_methods, AttributeError_members,
- 0, BaseException_str, "Attribute not found.");
+ 0, BaseException_str, 0, "Attribute not found.");
/*
* SyntaxError extends Exception
@@ -2558,7 +2622,7 @@ static PyMemberDef SyntaxError_members[] = {
ComplexExtendsException(PyExc_Exception, SyntaxError, SyntaxError,
0, 0, SyntaxError_members, 0,
- SyntaxError_str, "Invalid syntax.");
+ SyntaxError_str, 0, "Invalid syntax.");
/*
@@ -2616,7 +2680,7 @@ KeyError_str(PyBaseExceptionObject *self)
}
ComplexExtendsException(PyExc_LookupError, KeyError, BaseException,
- 0, 0, 0, 0, KeyError_str, "Mapping key not found.");
+ 0, 0, 0, 0, KeyError_str, 0, "Mapping key not found.");
/*
diff --git a/contrib/tools/python3/Objects/floatobject.c b/contrib/tools/python3/Objects/floatobject.c
index 14a98f542fa..986edd597d6 100644
--- a/contrib/tools/python3/Objects/floatobject.c
+++ b/contrib/tools/python3/Objects/floatobject.c
@@ -469,82 +469,67 @@ float_richcompare(PyObject *v, PyObject *w, int op)
assert(vsign != 0); /* if vsign were 0, then since wsign is
* not 0, we would have taken the
* vsign != wsign branch at the start */
- /* We want to work with non-negative numbers. */
- if (vsign < 0) {
- /* "Multiply both sides" by -1; this also swaps the
- * comparator.
- */
- i = -i;
- op = _Py_SwappedOp[op];
- }
- assert(i > 0.0);
(void) frexp(i, &exponent);
/* exponent is the # of bits in v before the radix point;
* we know that nbits (the # of bits in w) > 48 at this point
*/
if (exponent < 0 || (size_t)exponent < nbits) {
- i = 1.0;
- j = 2.0;
+ j = i;
+ i = 0.0;
goto Compare;
}
if ((size_t)exponent > nbits) {
- i = 2.0;
- j = 1.0;
+ j = 0.0;
goto Compare;
}
/* v and w have the same number of bits before the radix
- * point. Construct two ints that have the same comparison
- * outcome.
+ * point. Construct an int from the integer part of v and
+ * update op if necessary, so comparing two ints has the same outcome.
*/
{
double fracpart;
double intpart;
PyObject *result = NULL;
PyObject *vv = NULL;
- PyObject *ww = w;
- if (wsign < 0) {
- ww = PyNumber_Negative(w);
- if (ww == NULL)
- goto Error;
+ fracpart = modf(i, &intpart);
+ if (fracpart != 0.0) {
+ switch (op) {
+ /* Non-integer float never equals to an int. */
+ case Py_EQ:
+ Py_RETURN_FALSE;
+ case Py_NE:
+ Py_RETURN_TRUE;
+ /* For non-integer float, v <= w <=> v < w.
+ * If v > 0: trunc(v) < v < trunc(v) + 1
+ * v < w => trunc(v) < w
+ * trunc(v) < w => trunc(v) + 1 <= w => v < w
+ * If v < 0: trunc(v) - 1 < v < trunc(v)
+ * v < w => trunc(v) - 1 < w => trunc(v) <= w
+ * trunc(v) <= w => v < w
+ */
+ case Py_LT:
+ case Py_LE:
+ op = vsign > 0 ? Py_LT : Py_LE;
+ break;
+ /* The same as above, but with opposite directions. */
+ case Py_GT:
+ case Py_GE:
+ op = vsign > 0 ? Py_GE : Py_GT;
+ break;
+ }
}
- else
- Py_INCREF(ww);
- fracpart = modf(i, &intpart);
vv = PyLong_FromDouble(intpart);
if (vv == NULL)
goto Error;
- if (fracpart != 0.0) {
- /* Shift left, and or a 1 bit into vv
- * to represent the lost fraction.
- */
- PyObject *temp;
-
- temp = _PyLong_Lshift(ww, 1);
- if (temp == NULL)
- goto Error;
- Py_SETREF(ww, temp);
-
- temp = _PyLong_Lshift(vv, 1);
- if (temp == NULL)
- goto Error;
- Py_SETREF(vv, temp);
-
- temp = PyNumber_Or(vv, _PyLong_GetOne());
- if (temp == NULL)
- goto Error;
- Py_SETREF(vv, temp);
- }
-
- r = PyObject_RichCompareBool(vv, ww, op);
+ r = PyObject_RichCompareBool(vv, w, op);
if (r < 0)
goto Error;
result = PyBool_FromLong(r);
Error:
Py_XDECREF(vv);
- Py_XDECREF(ww);
return result;
}
} /* else if (PyLong_Check(w)) */
diff --git a/contrib/tools/python3/Objects/genericaliasobject.c b/contrib/tools/python3/Objects/genericaliasobject.c
index 4bb84f054dd..8e59b3884cf 100644
--- a/contrib/tools/python3/Objects/genericaliasobject.c
+++ b/contrib/tools/python3/Objects/genericaliasobject.c
@@ -133,10 +133,15 @@ ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p)
return -1;
}
}
- PyObject *item = PyList_GET_ITEM(p, i);
+ PyObject *item = PyList_GetItemRef(p, i);
+ if (item == NULL) {
+ return -1; // list can be mutated in a callback
+ }
if (ga_repr_item(writer, item) < 0) {
+ Py_DECREF(item);
return -1;
}
+ Py_DECREF(item);
}
if (_PyUnicodeWriter_WriteASCIIString(writer, "]", 1) < 0) {
diff --git a/contrib/tools/python3/Objects/genobject.c b/contrib/tools/python3/Objects/genobject.c
index 0273dea958e..b19ff252ddb 100644
--- a/contrib/tools/python3/Objects/genobject.c
+++ b/contrib/tools/python3/Objects/genobject.c
@@ -366,6 +366,7 @@ gen_close(PyGenObject *gen, PyObject *args)
if (gen->gi_frame_state == FRAME_CREATED) {
gen->gi_frame_state = FRAME_COMPLETED;
+ gen_clear_frame(gen);
Py_RETURN_NONE;
}
if (FRAME_STATE_FINISHED(gen->gi_frame_state)) {
@@ -381,11 +382,12 @@ gen_close(PyGenObject *gen, PyObject *args)
}
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
if (is_resume(frame->instr_ptr)) {
+ bool no_unwind_tools = _PyEval_NoToolsForUnwind(_PyThreadState_GET());
/* We can safely ignore the outermost try block
* as it is automatically generated to handle
* StopIteration. */
int oparg = frame->instr_ptr->op.arg;
- if (oparg & RESUME_OPARG_DEPTH1_MASK) {
+ if (oparg & RESUME_OPARG_DEPTH1_MASK && no_unwind_tools) {
// RESUME after YIELD_VALUE and exception depth is 1
assert((oparg & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_FUNC_START);
gen->gi_frame_state = FRAME_COMPLETED;
diff --git a/contrib/tools/python3/Objects/longobject.c b/contrib/tools/python3/Objects/longobject.c
index 23f50c7ed28..06d9ae4742f 100644
--- a/contrib/tools/python3/Objects/longobject.c
+++ b/contrib/tools/python3/Objects/longobject.c
@@ -4324,10 +4324,10 @@ pylong_int_divmod(PyLongObject *v, PyLongObject *w,
if (result == NULL) {
return -1;
}
- if (!PyTuple_Check(result)) {
+ if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 2) {
Py_DECREF(result);
PyErr_SetString(PyExc_ValueError,
- "tuple is required from int_divmod()");
+ "tuple of length 2 is required from int_divmod()");
return -1;
}
PyObject *q = PyTuple_GET_ITEM(result, 0);
diff --git a/contrib/tools/python3/Objects/memoryobject.c b/contrib/tools/python3/Objects/memoryobject.c
index b1a58d6b40e..8dc53c9ccbb 100644
--- a/contrib/tools/python3/Objects/memoryobject.c
+++ b/contrib/tools/python3/Objects/memoryobject.c
@@ -2330,7 +2330,13 @@ memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
CHECK_RELEASED(self);
if (MV_C_CONTIGUOUS(self->flags)) {
- return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
+ // Prevent 'self' from being freed if computing len(sep) mutates 'self'
+ // in _Py_strhex_with_sep().
+ // See: https://github.com/python/cpython/issues/143195.
+ self->exports++;
+ PyObject *ret = _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
+ self->exports--;
+ return ret;
}
bytes = PyBytes_FromStringAndSize(NULL, src->len);
@@ -3068,9 +3074,16 @@ memory_hash(PyObject *_self)
"memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
return -1;
}
- if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
- /* Keep the original error message */
- return -1;
+ if (view->obj != NULL) {
+ // Prevent 'self' from being freed when computing the item's hash.
+ // See https://github.com/python/cpython/issues/142664.
+ self->exports++;
+ Py_hash_t h = PyObject_Hash(view->obj);
+ self->exports--;
+ if (h == -1) {
+ /* Keep the original error message */
+ return -1;
+ }
}
if (!MV_C_CONTIGUOUS(self->flags)) {
diff --git a/contrib/tools/python3/Objects/object.c b/contrib/tools/python3/Objects/object.c
index 0539bcbb462..c6d5e163528 100644
--- a/contrib/tools/python3/Objects/object.c
+++ b/contrib/tools/python3/Objects/object.c
@@ -691,7 +691,7 @@ _PyObject_IsFreed(PyObject *op)
}
-/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */
+/* For debugging convenience. */
void
_PyObject_Dump(PyObject* op)
{
diff --git a/contrib/tools/python3/Objects/setobject.c b/contrib/tools/python3/Objects/setobject.c
index 5ec627558ab..891987e3519 100644
--- a/contrib/tools/python3/Objects/setobject.c
+++ b/contrib/tools/python3/Objects/setobject.c
@@ -185,6 +185,9 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
found_unused_or_dummy:
if (freeslot == NULL)
goto found_unused;
+ if (freeslot->hash != -1) {
+ goto restart;
+ }
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
freeslot->key = key;
freeslot->hash = hash;
diff --git a/contrib/tools/python3/Objects/typeobject.c b/contrib/tools/python3/Objects/typeobject.c
index 1c902ba12df..da4c9986a22 100644
--- a/contrib/tools/python3/Objects/typeobject.c
+++ b/contrib/tools/python3/Objects/typeobject.c
@@ -967,6 +967,7 @@ static void
set_version_unlocked(PyTypeObject *tp, unsigned int version)
{
ASSERT_TYPE_LOCK_HELD();
+ assert(version == 0 || (tp->tp_versions_used != _Py_ATTR_CACHE_UNUSED));
#ifndef Py_GIL_DISABLED
if (version) {
tp->tp_versions_used++;
@@ -1109,6 +1110,10 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
PyObject *b = PyTuple_GET_ITEM(bases, i);
PyTypeObject *cls = _PyType_CAST(b);
+ if (cls->tp_versions_used >= _Py_ATTR_CACHE_UNUSED) {
+ goto clear;
+ }
+
if (!is_subtype_with_mro(lookup_tp_mro(type), type, cls)) {
goto clear;
}
@@ -1117,7 +1122,8 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
clear:
assert(!(type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
- set_version_unlocked(type, 0); /* 0 is not a valid version tag */
+ set_version_unlocked(type, 0); /* 0 is not a valid version tag */
+ type->tp_versions_used = _Py_ATTR_CACHE_UNUSED;
if (PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
// This field *must* be invalidated if the type is modified (see the
// comment on struct _specialization_cache):
@@ -1127,6 +1133,9 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
}
#define MAX_VERSIONS_PER_CLASS 1000
+#if _Py_ATTR_CACHE_UNUSED < MAX_VERSIONS_PER_CLASS
+#error "_Py_ATTR_CACHE_UNUSED must be bigger than max"
+#endif
static int
assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
@@ -1144,6 +1153,7 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
return 0;
}
if (type->tp_versions_used >= MAX_VERSIONS_PER_CLASS) {
+ /* (this includes `tp_versions_used == _Py_ATTR_CACHE_UNUSED`) */
return 0;
}
@@ -6112,12 +6122,6 @@ PyTypeObject PyType_Type = {
symmetrically, __new__() complains about excess arguments unless
__init__() is overridden and __new__() is not overridden
(IOW, if __new__() is overridden or __init__() is not overridden).
-
- However, for backwards compatibility, this breaks too much code.
- Therefore, in 2.6, we'll *warn* about excess arguments when both
- methods are overridden; for all other cases we'll use the above
- rules.
-
*/
/* Forward */
diff --git a/contrib/tools/python3/Objects/typevarobject.c b/contrib/tools/python3/Objects/typevarobject.c
index fa6c8d7367d..1398f911e54 100644
--- a/contrib/tools/python3/Objects/typevarobject.c
+++ b/contrib/tools/python3/Objects/typevarobject.c
@@ -1175,13 +1175,13 @@ The following syntax creates a parameter specification that defaults\n\
to a callable accepting two positional-only arguments of types int\n\
and str:\n\
\n\
- type IntFuncDefault[**P = (int, str)] = Callable[P, int]\n\
+ type IntFuncDefault[**P = [int, str]] = Callable[P, int]\n\
\n\
For compatibility with Python 3.11 and earlier, ParamSpec objects\n\
can also be created as follows::\n\
\n\
P = ParamSpec('P')\n\
- DefaultP = ParamSpec('DefaultP', default=(int, str))\n\
+ DefaultP = ParamSpec('DefaultP', default=[int, str])\n\
\n\
Parameter specification variables exist primarily for the benefit of\n\
static type checkers. They are used to forward the parameter types of\n\
diff --git a/contrib/tools/python3/PC/winreg.c b/contrib/tools/python3/PC/winreg.c
index ed2cce51cb7..b81b0590eb9 100644
--- a/contrib/tools/python3/PC/winreg.c
+++ b/contrib/tools/python3/PC/winreg.c
@@ -1660,7 +1660,7 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const wchar_t *name)
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValueEx");
}
- obData = Reg2Py(retBuf, bufSize, typ);
+ obData = Reg2Py(retBuf, retSize, typ);
PyMem_Free(retBuf);
if (obData == NULL)
return NULL;
diff --git a/contrib/tools/python3/Parser/pegen_errors.c b/contrib/tools/python3/Parser/pegen_errors.c
index d692d6b0c86..b5e7b12b93c 100644
--- a/contrib/tools/python3/Parser/pegen_errors.c
+++ b/contrib/tools/python3/Parser/pegen_errors.c
@@ -35,7 +35,7 @@ _PyPegen_raise_tokenizer_init_error(PyObject *filename)
tuple = PyTuple_Pack(2, errstr, tmp);
Py_DECREF(tmp);
- if (!value) {
+ if (!tuple) {
goto error;
}
PyErr_SetObject(PyExc_SyntaxError, tuple);
diff --git a/contrib/tools/python3/Python/Python-ast.c b/contrib/tools/python3/Python/Python-ast.c
index a71262c7f84..1871ca3fb3d 100644
--- a/contrib/tools/python3/Python/Python-ast.c
+++ b/contrib/tools/python3/Python/Python-ast.c
@@ -5136,7 +5136,7 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
}
if (p == 0) {
PyErr_Format(PyExc_TypeError,
- "%.400s got multiple values for argument '%U'",
+ "%.400s got multiple values for argument %R",
Py_TYPE(self)->tp_name, key);
res = -1;
goto cleanup;
@@ -5159,7 +5159,7 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
else if (contains == 0) {
if (PyErr_WarnFormat(
PyExc_DeprecationWarning, 1,
- "%.400s.__init__ got an unexpected keyword argument '%U'. "
+ "%.400s.__init__ got an unexpected keyword argument %R. "
"Support for arbitrary keyword arguments is deprecated "
"and will be removed in Python 3.15.",
Py_TYPE(self)->tp_name, key
diff --git a/contrib/tools/python3/Python/ceval.c b/contrib/tools/python3/Python/ceval.c
index 0be6c57c1cf..ca07bfbaaf6 100644
--- a/contrib/tools/python3/Python/ceval.c
+++ b/contrib/tools/python3/Python/ceval.c
@@ -1696,10 +1696,10 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
gen->gi_exc_state.previous_item = NULL;
tstate->c_recursion_remaining--;
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
+ frame->previous = NULL;
_PyFrame_ClearExceptCode(frame);
_PyErr_ClearExcState(&gen->gi_exc_state);
tstate->c_recursion_remaining++;
- frame->previous = NULL;
}
void
@@ -2272,6 +2272,10 @@ monitor_unwind(PyThreadState *tstate,
do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_UNWIND);
}
+bool
+_PyEval_NoToolsForUnwind(PyThreadState *tstate) {
+ return no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_UNWIND);
+}
static int
monitor_handled(PyThreadState *tstate,
diff --git a/contrib/tools/python3/Python/context.c b/contrib/tools/python3/Python/context.c
index c9675f44772..1b2797b8af5 100644
--- a/contrib/tools/python3/Python/context.c
+++ b/contrib/tools/python3/Python/context.c
@@ -264,12 +264,6 @@ PyContextVar_Set(PyObject *ovar, PyObject *val)
ENSURE_ContextVar(ovar, NULL)
PyContextVar *var = (PyContextVar *)ovar;
- if (!PyContextVar_CheckExact(var)) {
- PyErr_SetString(
- PyExc_TypeError, "an instance of ContextVar was expected");
- return NULL;
- }
-
PyContext *ctx = context_get();
if (ctx == NULL) {
return NULL;
@@ -979,12 +973,6 @@ static PyObject *
_contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value)
/*[clinic end generated code: output=0746bd0aa2ced7bf input=30aa2ab9e433e401]*/
{
- if (!PyContextVar_CheckExact(self)) {
- PyErr_SetString(
- PyExc_TypeError, "an instance of ContextVar was expected");
- return NULL;
- }
-
PyObject *val;
if (PyContextVar_Get((PyObject *)self, default_value, &val) < 0) {
return NULL;
diff --git a/contrib/tools/python3/Python/crossinterp.c b/contrib/tools/python3/Python/crossinterp.c
index 2f6324d300d..d150c6e03c0 100644
--- a/contrib/tools/python3/Python/crossinterp.c
+++ b/contrib/tools/python3/Python/crossinterp.c
@@ -337,7 +337,7 @@ _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *data)
/* convenience utilities */
/*************************/
-static const char *
+static char *
_copy_string_obj_raw(PyObject *strobj, Py_ssize_t *p_size)
{
Py_ssize_t size = -1;
@@ -441,11 +441,16 @@ _format_TracebackException(PyObject *tbexc)
}
Py_ssize_t size = -1;
- const char *formatted = _copy_string_obj_raw(formatted_obj, &size);
+ char *formatted = _copy_string_obj_raw(formatted_obj, &size);
Py_DECREF(formatted_obj);
- // We remove trailing the newline added by TracebackException.format().
- assert(formatted[size-1] == '\n');
- ((char *)formatted)[size-1] = '\0';
+ if (formatted == NULL || size == 0) {
+ return formatted;
+ }
+ assert(formatted[size] == '\0');
+ // Remove a trailing newline if needed.
+ if (formatted[size-1] == '\n') {
+ formatted[size-1] = '\0';
+ }
return formatted;
}
@@ -1687,6 +1692,7 @@ _PyXI_ApplyCapturedException(_PyXI_session *session)
assert(session->error != NULL);
PyObject *res = _PyXI_ApplyError(session->error);
assert((res == NULL) != (PyErr_Occurred() == NULL));
+ _PyXI_excinfo_Clear(&session->error->uncaught);
session->error = NULL;
return res;
}
diff --git a/contrib/tools/python3/Python/errors.c b/contrib/tools/python3/Python/errors.c
index 63e4844b1c0..b565722ef56 100644
--- a/contrib/tools/python3/Python/errors.c
+++ b/contrib/tools/python3/Python/errors.c
@@ -1598,6 +1598,7 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
_Py_EnsureTstateNotNULL(tstate);
PyObject *err_msg = NULL;
+ PyObject *hook = NULL;
PyObject *exc_type, *exc_value, *exc_tb;
_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
@@ -1642,7 +1643,6 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
goto error;
}
- PyObject *hook;
if (_PySys_GetOptionalAttr(&_Py_ID(unraisablehook), &hook) < 0) {
Py_DECREF(hook_args);
err_msg_str = NULL;
@@ -1655,7 +1655,6 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
}
if (_PySys_Audit(tstate, "sys.unraisablehook", "OO", hook, hook_args) < 0) {
- Py_DECREF(hook);
Py_DECREF(hook_args);
err_msg_str = "Exception ignored in audit hook";
obj = NULL;
@@ -1663,13 +1662,11 @@ format_unraisable_v(const char *format, va_list va, PyObject *obj)
}
if (hook == Py_None) {
- Py_DECREF(hook);
Py_DECREF(hook_args);
goto default_hook;
}
PyObject *res = PyObject_CallOneArg(hook, hook_args);
- Py_DECREF(hook);
Py_DECREF(hook_args);
if (res != NULL) {
Py_DECREF(res);
@@ -1699,6 +1696,7 @@ done:
Py_XDECREF(exc_value);
Py_XDECREF(exc_tb);
Py_XDECREF(err_msg);
+ Py_XDECREF(hook);
_PyErr_Clear(tstate); /* Just in case */
}
diff --git a/contrib/tools/python3/Python/frozen_modules/_sitebuiltins.h b/contrib/tools/python3/Python/frozen_modules/_sitebuiltins.h
index 5913f78f1a3..4455a6bdb0d 100644
--- a/contrib/tools/python3/Python/frozen_modules/_sitebuiltins.h
+++ b/contrib/tools/python3/Python/frozen_modules/_sitebuiltins.h
@@ -85,7 +85,7 @@ const unsigned char _Py_M___sitebuiltins[] = {
0,0,0,0,0,0,9,0,0,0,3,0,0,0,243,184,
0,0,0,149,0,83,1,83,0,75,0,110,5,88,16,108,
1,0,0,0,0,0,0,0,0,88,32,108,2,0,0,0,
- 0,0,0,0,0,83,0,85,0,108,3,0,0,0,0,0,
+ 0,0,0,0,0,47,0,85,0,108,3,0,0,0,0,0,
0,0,0,85,4,19,0,86,6,86,7,115,3,47,0,115,
2,19,0,72,40,0,0,110,6,85,3,19,0,19,0,72,
30,0,0,110,7,85,5,82,8,0,0,0,0,0,0,0,
@@ -108,7 +108,7 @@ const unsigned char _Py_M___sitebuiltins[] = {
114,13,0,0,0,218,17,95,80,114,105,110,116,101,114,46,
95,95,105,110,105,116,95,95,35,0,0,0,115,85,0,0,
0,128,0,219,8,17,216,22,26,140,11,216,22,26,140,11,
- 216,23,27,136,4,140,12,225,39,43,244,3,2,28,51,218,
+ 216,23,25,136,4,140,12,225,39,43,244,3,2,28,51,218,
39,43,160,3,220,44,49,160,8,240,5,0,29,31,159,71,
153,71,159,76,153,76,168,19,214,28,55,225,44,49,241,5,
0,29,56,217,39,43,242,3,2,28,51,136,4,213,8,24,
@@ -188,121 +188,101 @@ const unsigned char _Py_M___sitebuiltins[] = {
12,42,224,19,54,184,52,191,59,185,59,184,46,200,17,209,
58,74,209,19,75,208,12,75,114,15,0,0,0,99,1,0,
0,0,0,0,0,0,0,0,0,0,5,0,0,0,3,0,
- 0,0,243,38,1,0,0,149,0,85,0,82,1,0,0,0,
+ 0,0,243,148,0,0,0,149,0,83,1,83,2,75,0,74,
+ 1,110,1,32,0,85,0,82,5,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,53,0,0,0,0,
+ 0,0,0,32,0,85,1,34,0,53,0,0,0,0,0,0,
+ 0,110,2,83,3,82,7,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,85,0,82,8,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,53,
- 0,0,0,0,0,0,0,32,0,83,1,110,1,83,2,110,
- 2,30,0,30,0,91,3,0,0,0,0,0,0,0,0,88,
- 34,85,0,82,4,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,45,0,0,0,53,2,0,0,0,
- 0,0,0,19,0,72,27,0,0,110,3,91,7,0,0,0,
- 0,0,0,0,0,85,0,82,8,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,85,3,5,0,0,
- 0,53,1,0,0,0,0,0,0,32,0,77,29,0,0,11,
- 0,32,0,88,32,82,4,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,45,13,0,0,110,2,83,
- 0,110,4,85,4,99,24,0,0,91,11,0,0,0,0,0,
- 0,0,0,85,1,53,1,0,0,0,0,0,0,110,4,85,
- 4,83,3,59,1,0,0,97,2,0,0,83,0,110,4,85,
- 4,99,2,0,0,77,24,0,0,85,4,83,4,58,88,0,
- 0,97,1,0,0,103,0,30,0,77,109,0,0,33,0,91,
- 12,0,0,0,0,0,0,0,0,7,0,97,3,0,0,32,
- 0,31,0,103,0,102,0,61,3,31,0,102,1,41,5,78,
- 122,48,72,105,116,32,82,101,116,117,114,110,32,102,111,114,
- 32,109,111,114,101,44,32,111,114,32,113,32,40,97,110,100,
- 32,82,101,116,117,114,110,41,32,116,111,32,113,117,105,116,
- 58,32,114,2,0,0,0,41,2,218,0,218,1,113,114,72,
- 0,0,0,41,7,114,67,0,0,0,218,5,114,97,110,103,
- 101,114,68,0,0,0,218,5,112,114,105,110,116,114,43,0,
- 0,0,218,5,105,110,112,117,116,218,10,73,110,100,101,120,
- 69,114,114,111,114,41,5,114,11,0,0,0,218,6,112,114,
- 111,109,112,116,218,6,108,105,110,101,110,111,218,1,105,218,
- 3,107,101,121,115,5,0,0,0,32,32,32,32,32,114,12,
- 0,0,0,114,26,0,0,0,218,17,95,80,114,105,110,116,
- 101,114,46,95,95,99,97,108,108,95,95,67,0,0,0,115,
- 164,0,0,0,128,0,216,8,12,143,12,137,12,140,14,216,
- 17,67,136,6,216,17,18,136,6,216,14,15,240,2,13,13,
- 26,220,25,30,152,118,176,4,183,13,177,13,209,39,61,214,
- 25,62,144,65,220,20,25,152,36,159,44,153,44,160,113,153,
- 47,214,20,42,241,3,0,26,63,240,10,0,17,23,159,45,
- 153,45,209,16,39,144,6,216,22,26,144,3,216,22,25,145,
- 107,220,26,31,160,6,155,45,144,67,216,23,26,160,41,211,
- 23,43,216,30,34,152,3,240,7,0,23,26,147,107,240,8,
- 0,20,23,152,35,147,58,216,20,25,240,3,0,20,30,241,
- 27,0,15,16,248,244,8,0,20,30,243,0,1,13,22,217,
- 16,21,240,3,1,13,22,250,115,17,0,0,0,151,55,66,
- 3,0,194,3,10,66,16,3,194,15,1,66,16,3,41,5,
- 218,6,95,95,100,97,116,97,218,11,95,95,102,105,108,101,
- 110,97,109,101,115,218,9,95,95,108,105,110,101,99,110,116,
- 218,7,95,95,108,105,110,101,115,218,6,95,95,110,97,109,
- 101,78,41,2,114,33,0,0,0,114,33,0,0,0,41,11,
- 114,28,0,0,0,114,29,0,0,0,114,30,0,0,0,114,
- 31,0,0,0,218,7,95,95,100,111,99,95,95,114,68,0,
- 0,0,114,13,0,0,0,114,67,0,0,0,114,18,0,0,
- 0,114,26,0,0,0,114,32,0,0,0,114,33,0,0,0,
- 114,15,0,0,0,114,12,0,0,0,114,35,0,0,0,114,
- 35,0,0,0,29,0,0,0,115,35,0,0,0,134,0,241,
- 2,1,5,46,240,6,0,16,18,128,72,244,4,7,5,51,
- 242,18,14,5,43,242,32,5,5,76,1,245,14,18,5,26,
- 114,15,0,0,0,114,35,0,0,0,99,0,0,0,0,0,
- 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,243,
- 36,0,0,0,149,0,92,0,114,1,83,0,114,2,83,1,
- 114,3,83,2,114,4,83,3,26,0,114,5,83,4,26,0,
- 114,6,83,5,114,7,103,6,41,7,218,7,95,72,101,108,
- 112,101,114,233,88,0,0,0,97,31,1,0,0,68,101,102,
- 105,110,101,32,116,104,101,32,98,117,105,108,116,105,110,32,
- 39,104,101,108,112,39,46,10,10,84,104,105,115,32,105,115,
- 32,97,32,119,114,97,112,112,101,114,32,97,114,111,117,110,
- 100,32,112,121,100,111,99,46,104,101,108,112,32,116,104,97,
- 116,32,112,114,111,118,105,100,101,115,32,97,32,104,101,108,
- 112,102,117,108,32,109,101,115,115,97,103,101,10,119,104,101,
- 110,32,39,104,101,108,112,39,32,105,115,32,116,121,112,101,
- 100,32,97,116,32,116,104,101,32,80,121,116,104,111,110,32,
- 105,110,116,101,114,97,99,116,105,118,101,32,112,114,111,109,
- 112,116,46,10,10,67,97,108,108,105,110,103,32,104,101,108,
- 112,40,41,32,97,116,32,116,104,101,32,80,121,116,104,111,
- 110,32,112,114,111,109,112,116,32,115,116,97,114,116,115,32,
- 97,110,32,105,110,116,101,114,97,99,116,105,118,101,32,104,
- 101,108,112,32,115,101,115,115,105,111,110,46,10,67,97,108,
- 108,105,110,103,32,104,101,108,112,40,116,104,105,110,103,41,
- 32,112,114,105,110,116,115,32,104,101,108,112,32,102,111,114,
- 32,116,104,101,32,112,121,116,104,111,110,32,111,98,106,101,
- 99,116,32,39,116,104,105,110,103,39,46,10,99,1,0,0,
- 0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,
- 0,243,4,0,0,0,149,0,103,1,41,2,78,122,72,84,
- 121,112,101,32,104,101,108,112,40,41,32,102,111,114,32,105,
- 110,116,101,114,97,99,116,105,118,101,32,104,101,108,112,44,
- 32,111,114,32,104,101,108,112,40,111,98,106,101,99,116,41,
- 32,102,111,114,32,104,101,108,112,32,97,98,111,117,116,32,
- 111,98,106,101,99,116,46,114,33,0,0,0,114,17,0,0,
- 0,115,1,0,0,0,32,114,12,0,0,0,114,18,0,0,
- 0,218,16,95,72,101,108,112,101,114,46,95,95,114,101,112,
- 114,95,95,98,0,0,0,115,7,0,0,0,128,0,240,2,
- 1,16,56,114,15,0,0,0,99,1,0,0,0,0,0,0,
- 0,0,0,0,0,5,0,0,0,15,0,0,0,243,46,0,
- 0,0,149,0,83,1,83,0,75,0,110,3,85,3,82,2,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,34,0,85,1,48,0,85,2,68,1,54,1,36,0,
- 114,39,0,0,0,41,2,218,5,112,121,100,111,99,218,4,
- 104,101,108,112,41,4,114,11,0,0,0,218,4,97,114,103,
- 115,218,4,107,119,100,115,114,94,0,0,0,115,4,0,0,
- 0,32,32,32,32,114,12,0,0,0,114,26,0,0,0,218,
- 16,95,72,101,108,112,101,114,46,95,95,99,97,108,108,95,
- 95,101,0,0,0,115,25,0,0,0,128,0,219,8,20,216,
- 15,20,143,122,138,122,152,52,208,15,40,160,52,209,15,40,
- 208,8,40,114,15,0,0,0,114,33,0,0,0,78,41,8,
- 114,28,0,0,0,114,29,0,0,0,114,30,0,0,0,114,
- 31,0,0,0,114,87,0,0,0,114,18,0,0,0,114,26,
- 0,0,0,114,32,0,0,0,114,33,0,0,0,114,15,0,
- 0,0,114,12,0,0,0,114,89,0,0,0,114,89,0,0,
- 0,88,0,0,0,115,17,0,0,0,134,0,241,2,7,5,
- 8,242,18,2,5,56,245,6,2,5,41,114,15,0,0,0,
- 114,89,0,0,0,41,6,114,87,0,0,0,114,21,0,0,
- 0,218,6,111,98,106,101,99,116,114,4,0,0,0,114,35,
- 0,0,0,114,89,0,0,0,114,33,0,0,0,114,15,0,
- 0,0,114,12,0,0,0,218,8,60,109,111,100,117,108,101,
- 62,114,100,0,0,0,1,0,0,0,115,52,0,0,0,240,
- 3,1,1,1,241,2,2,1,4,243,20,0,1,11,244,4,
- 13,1,31,136,102,244,0,13,1,31,244,32,56,1,26,136,
- 118,244,0,56,1,26,244,118,1,15,1,41,136,102,245,0,
- 15,1,41,114,15,0,0,0,
+ 1,0,0,0,0,0,0,110,3,85,2,34,0,88,48,82,
+ 10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,83,4,57,2,32,0,103,0,41,5,78,114,2,
+ 0,0,0,41,1,218,9,103,101,116,95,112,97,103,101,114,
+ 114,55,0,0,0,41,1,218,5,116,105,116,108,101,41,6,
+ 218,13,95,112,121,114,101,112,108,46,112,97,103,101,114,114,
+ 71,0,0,0,114,67,0,0,0,114,45,0,0,0,114,43,
+ 0,0,0,114,41,0,0,0,41,4,114,11,0,0,0,114,
+ 71,0,0,0,218,5,112,97,103,101,114,218,4,116,101,120,
+ 116,115,4,0,0,0,32,32,32,32,114,12,0,0,0,114,
+ 26,0,0,0,218,17,95,80,114,105,110,116,101,114,46,95,
+ 95,99,97,108,108,95,95,67,0,0,0,115,51,0,0,0,
+ 128,0,221,8,43,216,8,12,143,12,137,12,140,14,225,16,
+ 25,147,11,136,5,216,15,19,143,121,137,121,152,20,159,28,
+ 153,28,211,15,38,136,4,217,8,13,136,100,159,43,153,43,
+ 211,8,38,114,15,0,0,0,41,5,218,6,95,95,100,97,
+ 116,97,218,11,95,95,102,105,108,101,110,97,109,101,115,218,
+ 9,95,95,108,105,110,101,99,110,116,218,7,95,95,108,105,
+ 110,101,115,218,6,95,95,110,97,109,101,78,41,2,114,33,
+ 0,0,0,114,33,0,0,0,41,11,114,28,0,0,0,114,
+ 29,0,0,0,114,30,0,0,0,114,31,0,0,0,218,7,
+ 95,95,100,111,99,95,95,114,68,0,0,0,114,13,0,0,
+ 0,114,67,0,0,0,114,18,0,0,0,114,26,0,0,0,
+ 114,32,0,0,0,114,33,0,0,0,114,15,0,0,0,114,
+ 12,0,0,0,114,35,0,0,0,114,35,0,0,0,29,0,
+ 0,0,115,35,0,0,0,134,0,241,2,1,5,46,240,6,
+ 0,16,18,128,72,244,4,7,5,51,242,18,14,5,43,242,
+ 32,5,5,76,1,245,14,6,5,39,114,15,0,0,0,114,
+ 35,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0,243,36,0,0,0,149,0,
+ 92,0,114,1,83,0,114,2,83,1,114,3,83,2,114,4,
+ 83,3,26,0,114,5,83,4,26,0,114,6,83,5,114,7,
+ 103,6,41,7,218,7,95,72,101,108,112,101,114,233,76,0,
+ 0,0,97,31,1,0,0,68,101,102,105,110,101,32,116,104,
+ 101,32,98,117,105,108,116,105,110,32,39,104,101,108,112,39,
+ 46,10,10,84,104,105,115,32,105,115,32,97,32,119,114,97,
+ 112,112,101,114,32,97,114,111,117,110,100,32,112,121,100,111,
+ 99,46,104,101,108,112,32,116,104,97,116,32,112,114,111,118,
+ 105,100,101,115,32,97,32,104,101,108,112,102,117,108,32,109,
+ 101,115,115,97,103,101,10,119,104,101,110,32,39,104,101,108,
+ 112,39,32,105,115,32,116,121,112,101,100,32,97,116,32,116,
+ 104,101,32,80,121,116,104,111,110,32,105,110,116,101,114,97,
+ 99,116,105,118,101,32,112,114,111,109,112,116,46,10,10,67,
+ 97,108,108,105,110,103,32,104,101,108,112,40,41,32,97,116,
+ 32,116,104,101,32,80,121,116,104,111,110,32,112,114,111,109,
+ 112,116,32,115,116,97,114,116,115,32,97,110,32,105,110,116,
+ 101,114,97,99,116,105,118,101,32,104,101,108,112,32,115,101,
+ 115,115,105,111,110,46,10,67,97,108,108,105,110,103,32,104,
+ 101,108,112,40,116,104,105,110,103,41,32,112,114,105,110,116,
+ 115,32,104,101,108,112,32,102,111,114,32,116,104,101,32,112,
+ 121,116,104,111,110,32,111,98,106,101,99,116,32,39,116,104,
+ 105,110,103,39,46,10,99,1,0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,3,0,0,0,243,4,0,0,0,
+ 149,0,103,1,41,2,78,122,72,84,121,112,101,32,104,101,
+ 108,112,40,41,32,102,111,114,32,105,110,116,101,114,97,99,
+ 116,105,118,101,32,104,101,108,112,44,32,111,114,32,104,101,
+ 108,112,40,111,98,106,101,99,116,41,32,102,111,114,32,104,
+ 101,108,112,32,97,98,111,117,116,32,111,98,106,101,99,116,
+ 46,114,33,0,0,0,114,17,0,0,0,115,1,0,0,0,
+ 32,114,12,0,0,0,114,18,0,0,0,218,16,95,72,101,
+ 108,112,101,114,46,95,95,114,101,112,114,95,95,86,0,0,
+ 0,115,7,0,0,0,128,0,240,2,1,16,56,114,15,0,
+ 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,5,
+ 0,0,0,15,0,0,0,243,46,0,0,0,149,0,83,1,
+ 83,0,75,0,110,3,85,3,82,2,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,34,0,85,1,
+ 48,0,85,2,68,1,54,1,36,0,114,39,0,0,0,41,
+ 2,218,5,112,121,100,111,99,218,4,104,101,108,112,41,4,
+ 114,11,0,0,0,218,4,97,114,103,115,218,4,107,119,100,
+ 115,114,89,0,0,0,115,4,0,0,0,32,32,32,32,114,
+ 12,0,0,0,114,26,0,0,0,218,16,95,72,101,108,112,
+ 101,114,46,95,95,99,97,108,108,95,95,89,0,0,0,115,
+ 25,0,0,0,128,0,219,8,20,216,15,20,143,122,138,122,
+ 152,52,208,15,40,160,52,209,15,40,208,8,40,114,15,0,
+ 0,0,114,33,0,0,0,78,41,8,114,28,0,0,0,114,
+ 29,0,0,0,114,30,0,0,0,114,31,0,0,0,114,82,
+ 0,0,0,114,18,0,0,0,114,26,0,0,0,114,32,0,
+ 0,0,114,33,0,0,0,114,15,0,0,0,114,12,0,0,
+ 0,114,84,0,0,0,114,84,0,0,0,76,0,0,0,115,
+ 17,0,0,0,134,0,241,2,7,5,8,242,18,2,5,56,
+ 245,6,2,5,41,114,15,0,0,0,114,84,0,0,0,41,
+ 6,114,82,0,0,0,114,21,0,0,0,218,6,111,98,106,
+ 101,99,116,114,4,0,0,0,114,35,0,0,0,114,84,0,
+ 0,0,114,33,0,0,0,114,15,0,0,0,114,12,0,0,
+ 0,218,8,60,109,111,100,117,108,101,62,114,95,0,0,0,
+ 1,0,0,0,115,52,0,0,0,240,3,1,1,1,241,2,
+ 2,1,4,243,20,0,1,11,244,4,13,1,31,136,102,244,
+ 0,13,1,31,244,32,44,1,39,136,118,244,0,44,1,39,
+ 244,94,1,15,1,41,136,102,245,0,15,1,41,114,15,0,
+ 0,0,
};
diff --git a/contrib/tools/python3/Python/frozen_modules/stat.h b/contrib/tools/python3/Python/frozen_modules/stat.h
index 62b2f11b8a2..0f7254b5fa9 100644
--- a/contrib/tools/python3/Python/frozen_modules/stat.h
+++ b/contrib/tools/python3/Python/frozen_modules/stat.h
@@ -186,162 +186,170 @@ const unsigned char _Py_M__stat[] = {
0,64,218,1,108,218,1,115,218,1,45,218,1,98,218,1,
100,218,1,99,218,1,112,218,1,114,218,1,119,218,1,83,
218,1,120,218,1,116,218,1,84,99,1,0,0,0,0,0,
- 0,0,0,0,0,0,5,0,0,0,3,0,0,0,243,250,
- 0,0,0,149,0,47,0,110,1,91,1,0,0,0,0,0,
+ 0,0,0,0,0,0,5,0,0,0,3,0,0,0,243,80,
+ 1,0,0,149,0,47,0,110,1,91,1,0,0,0,0,0,
0,0,0,91,2,0,0,0,0,0,0,0,0,53,1,0,
- 0,0,0,0,0,19,0,72,86,0,0,117,2,0,0,112,
- 35,85,3,19,0,72,33,0,0,117,2,0,0,112,69,88,
- 4,45,1,0,0,85,4,58,88,0,0,100,2,0,0,77,
- 15,0,0,85,1,82,5,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,85,5,53,1,0,0,0,
- 0,0,0,32,0,32,0,77,42,0,0,11,0,32,0,85,
- 2,83,1,58,88,0,0,97,19,0,0,85,1,82,5,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,83,2,53,1,0,0,0,0,0,0,32,0,77,69,0,
- 0,85,1,82,5,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,83,3,53,1,0,0,0,0,0,
- 0,32,0,77,88,0,0,11,0,32,0,83,4,82,7,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,85,1,53,1,0,0,0,0,0,0,36,0,41,5,122,
- 59,67,111,110,118,101,114,116,32,97,32,102,105,108,101,39,
- 115,32,109,111,100,101,32,116,111,32,97,32,115,116,114,105,
- 110,103,32,111,102,32,116,104,101,32,102,111,114,109,32,39,
- 45,114,119,120,114,119,120,114,119,120,39,46,114,2,0,0,
- 0,218,1,63,114,58,0,0,0,218,0,41,4,218,9,101,
- 110,117,109,101,114,97,116,101,218,15,95,102,105,108,101,109,
- 111,100,101,95,116,97,98,108,101,218,6,97,112,112,101,110,
- 100,218,4,106,111,105,110,41,6,114,15,0,0,0,218,4,
- 112,101,114,109,218,5,105,110,100,101,120,218,5,116,97,98,
- 108,101,218,3,98,105,116,218,4,99,104,97,114,115,6,0,
- 0,0,32,32,32,32,32,32,114,16,0,0,0,218,8,102,
- 105,108,101,109,111,100,101,114,81,0,0,0,164,0,0,0,
- 115,110,0,0,0,128,0,224,11,13,128,68,220,24,33,164,
- 47,214,24,50,137,12,136,5,219,25,30,137,73,136,67,216,
- 15,19,137,122,152,83,213,15,32,216,16,20,151,11,145,11,
- 152,68,212,16,33,218,16,21,241,7,0,26,31,240,10,0,
- 16,21,152,1,139,122,224,16,20,151,11,145,11,152,67,214,
- 16,32,224,16,20,151,11,145,11,152,67,214,16,32,241,21,
- 0,25,51,240,22,0,12,14,143,55,137,55,144,52,139,61,
- 208,4,24,114,18,0,0,0,41,1,218,1,42,78,41,92,
- 218,7,95,95,100,111,99,95,95,218,7,83,84,95,77,79,
- 68,69,218,6,83,84,95,73,78,79,218,6,83,84,95,68,
- 69,86,218,8,83,84,95,78,76,73,78,75,218,6,83,84,
- 95,85,73,68,218,6,83,84,95,71,73,68,218,7,83,84,
- 95,83,73,90,69,218,8,83,84,95,65,84,73,77,69,218,
- 8,83,84,95,77,84,73,77,69,218,8,83,84,95,67,84,
- 73,77,69,114,17,0,0,0,114,20,0,0,0,114,22,0,
- 0,0,114,26,0,0,0,114,29,0,0,0,114,32,0,0,
- 0,114,35,0,0,0,114,38,0,0,0,114,41,0,0,0,
- 218,8,83,95,73,70,68,79,79,82,218,8,83,95,73,70,
- 80,79,82,84,218,7,83,95,73,70,87,72,84,114,23,0,
- 0,0,114,27,0,0,0,114,30,0,0,0,114,33,0,0,
- 0,114,36,0,0,0,114,39,0,0,0,114,42,0,0,0,
- 114,44,0,0,0,114,47,0,0,0,114,49,0,0,0,218,
- 7,83,95,73,83,85,73,68,218,7,83,95,73,83,71,73,
- 68,218,7,83,95,69,78,70,77,84,218,7,83,95,73,83,
- 86,84,88,218,7,83,95,73,82,69,65,68,218,8,83,95,
- 73,87,82,73,84,69,218,7,83,95,73,69,88,69,67,218,
- 7,83,95,73,82,87,88,85,218,7,83,95,73,82,85,83,
- 82,218,7,83,95,73,87,85,83,82,218,7,83,95,73,88,
- 85,83,82,218,7,83,95,73,82,87,88,71,218,7,83,95,
- 73,82,71,82,80,218,7,83,95,73,87,71,82,80,218,7,
- 83,95,73,88,71,82,80,218,7,83,95,73,82,87,88,79,
- 218,7,83,95,73,82,79,84,72,218,7,83,95,73,87,79,
- 84,72,218,7,83,95,73,88,79,84,72,218,11,85,70,95,
- 83,69,84,84,65,66,76,69,218,9,85,70,95,78,79,68,
- 85,77,80,218,12,85,70,95,73,77,77,85,84,65,66,76,
- 69,218,9,85,70,95,65,80,80,69,78,68,218,9,85,70,
- 95,79,80,65,81,85,69,218,11,85,70,95,78,79,85,78,
- 76,73,78,75,218,13,85,70,95,67,79,77,80,82,69,83,
- 83,69,68,218,10,85,70,95,84,82,65,67,75,69,68,218,
- 12,85,70,95,68,65,84,65,86,65,85,76,84,218,9,85,
- 70,95,72,73,68,68,69,78,218,11,83,70,95,83,69,84,
- 84,65,66,76,69,218,11,83,70,95,65,82,67,72,73,86,
- 69,68,218,12,83,70,95,73,77,77,85,84,65,66,76,69,
- 218,9,83,70,95,65,80,80,69,78,68,218,13,83,70,95,
- 82,69,83,84,82,73,67,84,69,68,218,11,83,70,95,78,
- 79,85,78,76,73,78,75,218,11,83,70,95,83,78,65,80,
- 83,72,79,84,218,11,83,70,95,70,73,82,77,76,73,78,
- 75,218,11,83,70,95,68,65,84,65,76,69,83,83,114,73,
- 0,0,0,114,81,0,0,0,218,22,70,73,76,69,95,65,
- 84,84,82,73,66,85,84,69,95,65,82,67,72,73,86,69,
- 218,25,70,73,76,69,95,65,84,84,82,73,66,85,84,69,
- 95,67,79,77,80,82,69,83,83,69,68,218,21,70,73,76,
- 69,95,65,84,84,82,73,66,85,84,69,95,68,69,86,73,
- 67,69,218,24,70,73,76,69,95,65,84,84,82,73,66,85,
- 84,69,95,68,73,82,69,67,84,79,82,89,218,24,70,73,
- 76,69,95,65,84,84,82,73,66,85,84,69,95,69,78,67,
- 82,89,80,84,69,68,218,21,70,73,76,69,95,65,84,84,
- 82,73,66,85,84,69,95,72,73,68,68,69,78,218,31,70,
- 73,76,69,95,65,84,84,82,73,66,85,84,69,95,73,78,
- 84,69,71,82,73,84,89,95,83,84,82,69,65,77,218,21,
- 70,73,76,69,95,65,84,84,82,73,66,85,84,69,95,78,
- 79,82,77,65,76,218,34,70,73,76,69,95,65,84,84,82,
- 73,66,85,84,69,95,78,79,84,95,67,79,78,84,69,78,
- 84,95,73,78,68,69,88,69,68,218,28,70,73,76,69,95,
- 65,84,84,82,73,66,85,84,69,95,78,79,95,83,67,82,
- 85,66,95,68,65,84,65,218,22,70,73,76,69,95,65,84,
- 84,82,73,66,85,84,69,95,79,70,70,76,73,78,69,218,
- 23,70,73,76,69,95,65,84,84,82,73,66,85,84,69,95,
- 82,69,65,68,79,78,76,89,218,28,70,73,76,69,95,65,
- 84,84,82,73,66,85,84,69,95,82,69,80,65,82,83,69,
- 95,80,79,73,78,84,218,26,70,73,76,69,95,65,84,84,
- 82,73,66,85,84,69,95,83,80,65,82,83,69,95,70,73,
- 76,69,218,21,70,73,76,69,95,65,84,84,82,73,66,85,
- 84,69,95,83,89,83,84,69,77,218,24,70,73,76,69,95,
- 65,84,84,82,73,66,85,84,69,95,84,69,77,80,79,82,
- 65,82,89,218,22,70,73,76,69,95,65,84,84,82,73,66,
- 85,84,69,95,86,73,82,84,85,65,76,218,5,95,115,116,
- 97,116,218,11,73,109,112,111,114,116,69,114,114,111,114,114,
- 13,0,0,0,114,18,0,0,0,114,16,0,0,0,218,8,
- 60,109,111,100,117,108,101,62,114,154,0,0,0,1,0,0,
- 0,115,232,2,0,0,240,3,1,1,1,241,2,3,1,4,
- 240,14,0,12,13,128,7,216,11,12,128,6,216,11,12,128,
- 6,216,11,12,128,8,216,11,12,128,6,216,11,12,128,6,
- 216,11,12,128,7,216,11,12,128,8,216,11,12,128,8,216,
- 11,12,128,8,242,8,4,1,25,242,12,4,1,27,240,18,
- 0,12,20,128,7,216,11,19,128,7,216,11,19,128,7,216,
- 11,19,128,7,216,11,19,128,7,216,11,19,128,7,216,11,
- 19,128,8,224,11,12,128,8,216,11,12,128,8,216,10,11,
- 128,7,242,8,2,1,35,242,8,2,1,35,242,8,2,1,
- 35,242,8,2,1,35,242,8,2,1,35,242,8,2,1,35,
- 242,8,2,1,36,242,8,2,1,17,242,8,2,1,17,242,
- 8,2,1,17,240,12,0,11,17,128,7,216,10,16,128,7,
- 216,10,17,128,7,216,10,16,128,7,216,10,16,128,7,216,
- 11,17,128,8,216,10,16,128,7,216,10,16,128,7,216,10,
- 16,128,7,216,10,16,128,7,216,10,16,128,7,216,10,16,
+ 0,0,0,0,0,19,0,72,129,0,0,117,2,0,0,112,
+ 35,85,3,19,0,72,76,0,0,117,2,0,0,112,69,85,
+ 2,83,1,58,88,0,0,97,37,0,0,91,5,0,0,0,
+ 0,0,0,0,0,85,0,53,1,0,0,0,0,0,0,85,
+ 4,58,88,0,0,97,20,0,0,85,1,82,7,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,
+ 5,53,1,0,0,0,0,0,0,32,0,32,0,77,53,0,
+ 0,77,48,0,0,88,4,45,1,0,0,85,4,58,88,0,
+ 0,100,2,0,0,77,58,0,0,85,1,82,7,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,
+ 5,53,1,0,0,0,0,0,0,32,0,32,0,77,85,0,
+ 0,11,0,32,0,85,2,83,1,58,88,0,0,97,19,0,
+ 0,85,1,82,7,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,83,2,53,1,0,0,0,0,0,
+ 0,32,0,77,112,0,0,85,1,82,7,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,83,3,53,
+ 1,0,0,0,0,0,0,32,0,77,131,0,0,11,0,32,
+ 0,83,4,82,9,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,85,1,53,1,0,0,0,0,0,
+ 0,36,0,41,5,122,59,67,111,110,118,101,114,116,32,97,
+ 32,102,105,108,101,39,115,32,109,111,100,101,32,116,111,32,
+ 97,32,115,116,114,105,110,103,32,111,102,32,116,104,101,32,
+ 102,111,114,109,32,39,45,114,119,120,114,119,120,114,119,120,
+ 39,46,114,2,0,0,0,218,1,63,114,58,0,0,0,218,
+ 0,41,5,218,9,101,110,117,109,101,114,97,116,101,218,15,
+ 95,102,105,108,101,109,111,100,101,95,116,97,98,108,101,114,
+ 20,0,0,0,218,6,97,112,112,101,110,100,218,4,106,111,
+ 105,110,41,6,114,15,0,0,0,218,4,112,101,114,109,218,
+ 5,105,110,100,101,120,218,5,116,97,98,108,101,218,3,98,
+ 105,116,218,4,99,104,97,114,115,6,0,0,0,32,32,32,
+ 32,32,32,114,16,0,0,0,218,8,102,105,108,101,109,111,
+ 100,101,114,81,0,0,0,164,0,0,0,115,151,0,0,0,
+ 128,0,224,11,13,128,68,220,24,33,164,47,214,24,50,137,
+ 12,136,5,219,25,30,137,73,136,67,216,15,20,152,1,139,
+ 122,220,19,25,152,36,147,60,160,51,211,19,38,216,20,24,
+ 151,75,145,75,160,4,212,20,37,218,20,25,241,5,0,20,
+ 39,240,8,0,20,24,145,58,160,19,213,19,36,216,20,24,
+ 151,75,145,75,160,4,212,20,37,218,20,25,241,17,0,26,
+ 31,240,20,0,16,21,152,1,139,122,224,16,20,151,11,145,
+ 11,152,67,214,16,32,224,16,20,151,11,145,11,152,67,214,
+ 16,32,241,31,0,25,51,240,32,0,12,14,143,55,137,55,
+ 144,52,139,61,208,4,24,114,18,0,0,0,41,1,218,1,
+ 42,78,41,92,218,7,95,95,100,111,99,95,95,218,7,83,
+ 84,95,77,79,68,69,218,6,83,84,95,73,78,79,218,6,
+ 83,84,95,68,69,86,218,8,83,84,95,78,76,73,78,75,
+ 218,6,83,84,95,85,73,68,218,6,83,84,95,71,73,68,
+ 218,7,83,84,95,83,73,90,69,218,8,83,84,95,65,84,
+ 73,77,69,218,8,83,84,95,77,84,73,77,69,218,8,83,
+ 84,95,67,84,73,77,69,114,17,0,0,0,114,20,0,0,
+ 0,114,22,0,0,0,114,26,0,0,0,114,29,0,0,0,
+ 114,32,0,0,0,114,35,0,0,0,114,38,0,0,0,114,
+ 41,0,0,0,218,8,83,95,73,70,68,79,79,82,218,8,
+ 83,95,73,70,80,79,82,84,218,7,83,95,73,70,87,72,
+ 84,114,23,0,0,0,114,27,0,0,0,114,30,0,0,0,
+ 114,33,0,0,0,114,36,0,0,0,114,39,0,0,0,114,
+ 42,0,0,0,114,44,0,0,0,114,47,0,0,0,114,49,
+ 0,0,0,218,7,83,95,73,83,85,73,68,218,7,83,95,
+ 73,83,71,73,68,218,7,83,95,69,78,70,77,84,218,7,
+ 83,95,73,83,86,84,88,218,7,83,95,73,82,69,65,68,
+ 218,8,83,95,73,87,82,73,84,69,218,7,83,95,73,69,
+ 88,69,67,218,7,83,95,73,82,87,88,85,218,7,83,95,
+ 73,82,85,83,82,218,7,83,95,73,87,85,83,82,218,7,
+ 83,95,73,88,85,83,82,218,7,83,95,73,82,87,88,71,
+ 218,7,83,95,73,82,71,82,80,218,7,83,95,73,87,71,
+ 82,80,218,7,83,95,73,88,71,82,80,218,7,83,95,73,
+ 82,87,88,79,218,7,83,95,73,82,79,84,72,218,7,83,
+ 95,73,87,79,84,72,218,7,83,95,73,88,79,84,72,218,
+ 11,85,70,95,83,69,84,84,65,66,76,69,218,9,85,70,
+ 95,78,79,68,85,77,80,218,12,85,70,95,73,77,77,85,
+ 84,65,66,76,69,218,9,85,70,95,65,80,80,69,78,68,
+ 218,9,85,70,95,79,80,65,81,85,69,218,11,85,70,95,
+ 78,79,85,78,76,73,78,75,218,13,85,70,95,67,79,77,
+ 80,82,69,83,83,69,68,218,10,85,70,95,84,82,65,67,
+ 75,69,68,218,12,85,70,95,68,65,84,65,86,65,85,76,
+ 84,218,9,85,70,95,72,73,68,68,69,78,218,11,83,70,
+ 95,83,69,84,84,65,66,76,69,218,11,83,70,95,65,82,
+ 67,72,73,86,69,68,218,12,83,70,95,73,77,77,85,84,
+ 65,66,76,69,218,9,83,70,95,65,80,80,69,78,68,218,
+ 13,83,70,95,82,69,83,84,82,73,67,84,69,68,218,11,
+ 83,70,95,78,79,85,78,76,73,78,75,218,11,83,70,95,
+ 83,78,65,80,83,72,79,84,218,11,83,70,95,70,73,82,
+ 77,76,73,78,75,218,11,83,70,95,68,65,84,65,76,69,
+ 83,83,114,73,0,0,0,114,81,0,0,0,218,22,70,73,
+ 76,69,95,65,84,84,82,73,66,85,84,69,95,65,82,67,
+ 72,73,86,69,218,25,70,73,76,69,95,65,84,84,82,73,
+ 66,85,84,69,95,67,79,77,80,82,69,83,83,69,68,218,
+ 21,70,73,76,69,95,65,84,84,82,73,66,85,84,69,95,
+ 68,69,86,73,67,69,218,24,70,73,76,69,95,65,84,84,
+ 82,73,66,85,84,69,95,68,73,82,69,67,84,79,82,89,
+ 218,24,70,73,76,69,95,65,84,84,82,73,66,85,84,69,
+ 95,69,78,67,82,89,80,84,69,68,218,21,70,73,76,69,
+ 95,65,84,84,82,73,66,85,84,69,95,72,73,68,68,69,
+ 78,218,31,70,73,76,69,95,65,84,84,82,73,66,85,84,
+ 69,95,73,78,84,69,71,82,73,84,89,95,83,84,82,69,
+ 65,77,218,21,70,73,76,69,95,65,84,84,82,73,66,85,
+ 84,69,95,78,79,82,77,65,76,218,34,70,73,76,69,95,
+ 65,84,84,82,73,66,85,84,69,95,78,79,84,95,67,79,
+ 78,84,69,78,84,95,73,78,68,69,88,69,68,218,28,70,
+ 73,76,69,95,65,84,84,82,73,66,85,84,69,95,78,79,
+ 95,83,67,82,85,66,95,68,65,84,65,218,22,70,73,76,
+ 69,95,65,84,84,82,73,66,85,84,69,95,79,70,70,76,
+ 73,78,69,218,23,70,73,76,69,95,65,84,84,82,73,66,
+ 85,84,69,95,82,69,65,68,79,78,76,89,218,28,70,73,
+ 76,69,95,65,84,84,82,73,66,85,84,69,95,82,69,80,
+ 65,82,83,69,95,80,79,73,78,84,218,26,70,73,76,69,
+ 95,65,84,84,82,73,66,85,84,69,95,83,80,65,82,83,
+ 69,95,70,73,76,69,218,21,70,73,76,69,95,65,84,84,
+ 82,73,66,85,84,69,95,83,89,83,84,69,77,218,24,70,
+ 73,76,69,95,65,84,84,82,73,66,85,84,69,95,84,69,
+ 77,80,79,82,65,82,89,218,22,70,73,76,69,95,65,84,
+ 84,82,73,66,85,84,69,95,86,73,82,84,85,65,76,218,
+ 5,95,115,116,97,116,218,11,73,109,112,111,114,116,69,114,
+ 114,111,114,114,13,0,0,0,114,18,0,0,0,114,16,0,
+ 0,0,218,8,60,109,111,100,117,108,101,62,114,154,0,0,
+ 0,1,0,0,0,115,232,2,0,0,240,3,1,1,1,241,
+ 2,3,1,4,240,14,0,12,13,128,7,216,11,12,128,6,
+ 216,11,12,128,6,216,11,12,128,8,216,11,12,128,6,216,
+ 11,12,128,6,216,11,12,128,7,216,11,12,128,8,216,11,
+ 12,128,8,216,11,12,128,8,242,8,4,1,25,242,12,4,
+ 1,27,240,18,0,12,20,128,7,216,11,19,128,7,216,11,
+ 19,128,7,216,11,19,128,7,216,11,19,128,7,216,11,19,
+ 128,7,216,11,19,128,8,224,11,12,128,8,216,11,12,128,
+ 8,216,10,11,128,7,242,8,2,1,35,242,8,2,1,35,
+ 242,8,2,1,35,242,8,2,1,35,242,8,2,1,35,242,
+ 8,2,1,35,242,8,2,1,36,242,8,2,1,17,242,8,
+ 2,1,17,242,8,2,1,17,240,12,0,11,17,128,7,216,
+ 10,16,128,7,216,10,17,128,7,216,10,16,128,7,216,10,
+ 16,128,7,216,11,17,128,8,216,10,16,128,7,216,10,16,
128,7,216,10,16,128,7,216,10,16,128,7,216,10,16,128,
7,216,10,16,128,7,216,10,16,128,7,216,10,16,128,7,
- 216,10,16,128,7,240,6,0,16,26,128,11,216,15,25,128,
- 9,216,15,25,128,12,216,15,25,128,9,216,15,25,128,9,
- 216,15,25,128,11,216,16,26,128,13,216,15,25,128,10,216,
- 15,25,128,12,216,15,25,128,9,216,15,25,128,11,216,15,
- 25,128,11,216,15,25,128,12,216,15,25,128,9,216,16,26,
- 128,13,216,15,25,128,11,216,15,25,128,11,216,15,25,128,
- 11,216,15,25,128,11,240,12,0,7,14,144,115,208,5,27,
- 216,6,14,144,115,208,5,27,216,6,13,144,115,208,5,27,
- 216,6,13,144,115,208,5,27,216,6,13,144,115,208,5,27,
- 216,6,13,144,115,208,5,27,216,6,13,144,115,208,5,27,
- 240,13,6,5,29,240,16,0,7,14,144,115,208,5,27,208,
- 4,29,216,6,13,144,115,208,5,27,208,4,29,216,6,13,
- 136,103,129,111,144,115,208,5,27,216,6,13,144,115,208,5,
- 27,216,6,13,144,115,208,5,27,240,5,2,5,29,240,8,
- 0,7,14,144,115,208,5,27,208,4,29,216,6,13,144,115,
- 208,5,27,208,4,29,216,6,13,136,103,129,111,144,115,208,
- 5,27,216,6,13,144,115,208,5,27,216,6,13,144,115,208,
- 5,27,240,5,2,5,29,240,8,0,7,14,144,115,208,5,
- 27,208,4,29,216,6,13,144,115,208,5,27,208,4,29,216,
- 6,13,136,103,129,111,144,115,208,5,27,216,6,13,144,115,
- 208,5,27,216,6,13,144,115,208,5,27,240,5,2,5,29,
- 240,51,28,19,2,128,15,242,60,14,1,25,240,40,0,26,
- 28,208,0,22,216,28,32,208,0,25,216,24,26,208,0,21,
- 216,27,29,208,0,24,216,27,32,208,0,24,216,24,25,208,
- 0,21,216,34,39,208,0,31,216,24,27,208,0,21,216,37,
- 41,208,0,34,216,31,37,208,0,28,216,25,29,208,0,22,
- 216,26,27,208,0,23,216,31,35,208,0,28,216,29,32,208,
- 0,26,216,24,25,208,0,21,216,27,30,208,0,24,216,25,
- 30,208,0,22,240,8,3,1,9,221,4,23,248,216,7,18,
- 243,0,1,1,9,217,4,8,240,3,1,1,9,250,115,18,
- 0,0,0,196,24,5,68,30,0,196,30,6,68,39,3,196,
- 38,1,68,39,3,
+ 216,10,16,128,7,216,10,16,128,7,216,10,16,128,7,216,
+ 10,16,128,7,216,10,16,128,7,240,6,0,16,26,128,11,
+ 216,15,25,128,9,216,15,25,128,12,216,15,25,128,9,216,
+ 15,25,128,9,216,15,25,128,11,216,16,26,128,13,216,15,
+ 25,128,10,216,15,25,128,12,216,15,25,128,9,216,15,25,
+ 128,11,216,15,25,128,11,216,15,25,128,12,216,15,25,128,
+ 9,216,16,26,128,13,216,15,25,128,11,216,15,25,128,11,
+ 216,15,25,128,11,216,15,25,128,11,240,12,0,7,14,144,
+ 115,208,5,27,216,6,14,144,115,208,5,27,216,6,13,144,
+ 115,208,5,27,216,6,13,144,115,208,5,27,216,6,13,144,
+ 115,208,5,27,216,6,13,144,115,208,5,27,216,6,13,144,
+ 115,208,5,27,240,13,6,5,29,240,16,0,7,14,144,115,
+ 208,5,27,208,4,29,216,6,13,144,115,208,5,27,208,4,
+ 29,216,6,13,136,103,129,111,144,115,208,5,27,216,6,13,
+ 144,115,208,5,27,216,6,13,144,115,208,5,27,240,5,2,
+ 5,29,240,8,0,7,14,144,115,208,5,27,208,4,29,216,
+ 6,13,144,115,208,5,27,208,4,29,216,6,13,136,103,129,
+ 111,144,115,208,5,27,216,6,13,144,115,208,5,27,216,6,
+ 13,144,115,208,5,27,240,5,2,5,29,240,8,0,7,14,
+ 144,115,208,5,27,208,4,29,216,6,13,144,115,208,5,27,
+ 208,4,29,216,6,13,136,103,129,111,144,115,208,5,27,216,
+ 6,13,144,115,208,5,27,216,6,13,144,115,208,5,27,240,
+ 5,2,5,29,240,51,28,19,2,128,15,242,60,19,1,25,
+ 240,50,0,26,28,208,0,22,216,28,32,208,0,25,216,24,
+ 26,208,0,21,216,27,29,208,0,24,216,27,32,208,0,24,
+ 216,24,25,208,0,21,216,34,39,208,0,31,216,24,27,208,
+ 0,21,216,37,41,208,0,34,216,31,37,208,0,28,216,25,
+ 29,208,0,22,216,26,27,208,0,23,216,31,35,208,0,28,
+ 216,29,32,208,0,26,216,24,25,208,0,21,216,27,30,208,
+ 0,24,216,25,30,208,0,22,240,8,3,1,9,221,4,23,
+ 248,216,7,18,243,0,1,1,9,217,4,8,240,3,1,1,
+ 9,250,115,18,0,0,0,196,24,5,68,30,0,196,30,6,
+ 68,39,3,196,38,1,68,39,3,
};
diff --git a/contrib/tools/python3/Python/hamt.c b/contrib/tools/python3/Python/hamt.c
index 91abaecd3e7..a9f811f4422 100644
--- a/contrib/tools/python3/Python/hamt.c
+++ b/contrib/tools/python3/Python/hamt.c
@@ -2368,6 +2368,10 @@ _PyHamt_Eq(PyHamtObject *v, PyHamtObject *w)
return 0;
}
+ Py_INCREF(v);
+ Py_INCREF(w);
+
+ int res = 1;
PyHamtIteratorState iter;
hamt_iter_t iter_res;
hamt_find_t find_res;
@@ -2383,25 +2387,38 @@ _PyHamt_Eq(PyHamtObject *v, PyHamtObject *w)
find_res = hamt_find(w, v_key, &w_val);
switch (find_res) {
case F_ERROR:
- return -1;
+ res = -1;
+ goto done;
case F_NOT_FOUND:
- return 0;
+ res = 0;
+ goto done;
case F_FOUND: {
+ Py_INCREF(v_key);
+ Py_INCREF(v_val);
+ Py_INCREF(w_val);
int cmp = PyObject_RichCompareBool(v_val, w_val, Py_EQ);
+ Py_DECREF(v_key);
+ Py_DECREF(v_val);
+ Py_DECREF(w_val);
if (cmp < 0) {
- return -1;
+ res = -1;
+ goto done;
}
if (cmp == 0) {
- return 0;
+ res = 0;
+ goto done;
}
}
}
}
} while (iter_res != I_END);
- return 1;
+done:
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return res;
}
Py_ssize_t
diff --git a/contrib/tools/python3/Python/import.c b/contrib/tools/python3/Python/import.c
index 32a25e4478c..03a49ea0599 100644
--- a/contrib/tools/python3/Python/import.c
+++ b/contrib/tools/python3/Python/import.c
@@ -4678,6 +4678,7 @@ static PyObject *
_imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
/*[clinic end generated code: output=83249b827a4fde77 input=c31b954f4cf4e09d]*/
{
+ FILE *fp = NULL;
PyObject *mod = NULL;
PyThreadState *tstate = _PyThreadState_GET();
@@ -4720,16 +4721,12 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
/* We would move this (and the fclose() below) into
* _PyImport_GetModInitFunc(), but it isn't clear if the intervening
* code relies on fp still being open. */
- FILE *fp;
if (file != NULL) {
fp = _Py_fopen_obj(info.filename, "r");
if (fp == NULL) {
goto finally;
}
}
- else {
- fp = NULL;
- }
PyModInitFunction p0 = _PyImport_GetModInitFunc(&info, fp);
if (p0 == NULL) {
@@ -4753,12 +4750,10 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
}
#endif
- // XXX Shouldn't this happen in the error cases too (i.e. in "finally")?
- if (fp) {
+finally:
+ if (fp != NULL) {
fclose(fp);
}
-
-finally:
_Py_ext_module_loader_info_clear(&info);
return mod;
}
diff --git a/contrib/tools/python3/Python/initconfig.c b/contrib/tools/python3/Python/initconfig.c
index 7542cb0d375..0b5f917a0f5 100644
--- a/contrib/tools/python3/Python/initconfig.c
+++ b/contrib/tools/python3/Python/initconfig.c
@@ -1576,7 +1576,9 @@ config_read_env_vars(PyConfig *config)
_Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG");
_Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE");
_Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE");
- _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT");
+ if (!config->inspect && _Py_GetEnv(use_env, "PYTHONINSPECT")) {
+ config->inspect = 1;
+ }
int dont_write_bytecode = 0;
_Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
diff --git a/contrib/tools/python3/Python/marshal.c b/contrib/tools/python3/Python/marshal.c
index 76fa701b541..65481341bdf 100644
--- a/contrib/tools/python3/Python/marshal.c
+++ b/contrib/tools/python3/Python/marshal.c
@@ -362,6 +362,10 @@ w_object(PyObject *v, WFILE *p)
{
char flag = '\0';
+ if (p->error != WFERR_OK) {
+ return;
+ }
+
p->depth++;
if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
diff --git a/contrib/tools/python3/Python/perf_jit_trampoline.c b/contrib/tools/python3/Python/perf_jit_trampoline.c
index a44a74f58df..b03da66e92e 100644
--- a/contrib/tools/python3/Python/perf_jit_trampoline.c
+++ b/contrib/tools/python3/Python/perf_jit_trampoline.c
@@ -372,6 +372,7 @@ static void perf_map_jit_write_header(int pid, FILE* out_file) {
header.version = 1; // Current jitdump version
header.size = sizeof(Header); // Header size for validation
header.elf_mach_target = GetElfMachineArchitecture(); // Target architecture
+ header.reserved = 0; // padding reserved for future use
header.process_id = pid; // Process identifier
header.time_stamp = get_current_time_microseconds(); // Creation time
header.flags = 0; // No special flags currently used
@@ -1052,7 +1053,8 @@ static void* perf_map_jit_init(void) {
0 // Offset 0 (first page)
);
- if (perf_jit_map_state.mapped_buffer == NULL) {
+ if (perf_jit_map_state.mapped_buffer == MAP_FAILED) {
+ perf_jit_map_state.mapped_buffer = NULL;
close(fd);
return NULL; // Memory mapping failed
}
diff --git a/contrib/tools/python3/Python/perf_trampoline.c b/contrib/tools/python3/Python/perf_trampoline.c
index b1b787fc278..5589ec1c362 100644
--- a/contrib/tools/python3/Python/perf_trampoline.c
+++ b/contrib/tools/python3/Python/perf_trampoline.c
@@ -204,6 +204,43 @@ enum perf_trampoline_type {
#define perf_map_file _PyRuntime.ceval.perf.map_file
#define persist_after_fork _PyRuntime.ceval.perf.persist_after_fork
#define perf_trampoline_type _PyRuntime.ceval.perf.perf_trampoline_type
+#define prev_eval_frame _PyRuntime.ceval.perf.prev_eval_frame
+#define trampoline_refcount _PyRuntime.ceval.perf.trampoline_refcount
+#define code_watcher_id _PyRuntime.ceval.perf.code_watcher_id
+
+static void free_code_arenas(void);
+
+static void
+perf_trampoline_reset_state(void)
+{
+ free_code_arenas();
+ if (code_watcher_id >= 0) {
+ PyCode_ClearWatcher(code_watcher_id);
+ code_watcher_id = -1;
+ }
+ extra_code_index = -1;
+}
+
+static int
+perf_trampoline_code_watcher(PyCodeEvent event, PyCodeObject *co)
+{
+ if (event != PY_CODE_EVENT_DESTROY) {
+ return 0;
+ }
+ if (extra_code_index == -1) {
+ return 0;
+ }
+ py_trampoline f = NULL;
+ int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);
+ if (ret != 0 || f == NULL) {
+ return 0;
+ }
+ trampoline_refcount--;
+ if (trampoline_refcount == 0) {
+ perf_trampoline_reset_state();
+ }
+ return 0;
+}
static void
perf_map_write_entry(void *state, const void *code_addr,
@@ -405,6 +442,7 @@ py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame,
perf_code_arena->code_size, co);
_PyCode_SetExtra((PyObject *)co, extra_code_index,
(void *)new_trampoline);
+ trampoline_refcount++;
f = new_trampoline;
}
assert(f != NULL);
@@ -428,6 +466,7 @@ int PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *co)
}
trampoline_api.write_state(trampoline_api.state, new_trampoline,
perf_code_arena->code_size, co);
+ trampoline_refcount++;
return _PyCode_SetExtra((PyObject *)co, extra_code_index,
(void *)new_trampoline);
}
@@ -482,6 +521,10 @@ _PyPerfTrampoline_Init(int activate)
{
#ifdef PY_HAVE_PERF_TRAMPOLINE
PyThreadState *tstate = _PyThreadState_GET();
+ if (code_watcher_id == 0) {
+ // Initialize to -1 since 0 is a valid watcher ID
+ code_watcher_id = -1;
+ }
if (tstate->interp->eval_frame &&
tstate->interp->eval_frame != py_trampoline_evaluator) {
PyErr_SetString(PyExc_RuntimeError,
@@ -505,6 +548,13 @@ _PyPerfTrampoline_Init(int activate)
if (new_code_arena() < 0) {
return -1;
}
+ code_watcher_id = PyCode_AddWatcher(perf_trampoline_code_watcher);
+ if (code_watcher_id < 0) {
+ PyErr_FormatUnraisable("Failed to register code watcher for perf trampoline");
+ free_code_arenas();
+ return -1;
+ }
+ trampoline_refcount = 1; // Base refcount held by the system
perf_status = PERF_STATUS_OK;
}
#endif
@@ -526,17 +576,19 @@ _PyPerfTrampoline_Fini(void)
trampoline_api.free_state(trampoline_api.state);
perf_trampoline_type = PERF_TRAMPOLINE_UNSET;
}
- extra_code_index = -1;
+
+ // Prevent new trampolines from being created
perf_status = PERF_STATUS_NO_INIT;
-#endif
- return 0;
-}
-void _PyPerfTrampoline_FreeArenas(void) {
-#ifdef PY_HAVE_PERF_TRAMPOLINE
- free_code_arenas();
+ // Decrement base refcount. If refcount reaches 0, all code objects are already
+ // dead so clean up now. Otherwise, watcher remains active to clean up when last
+ // code object dies; extra_code_index stays valid so watcher can identify them.
+ trampoline_refcount--;
+ if (trampoline_refcount == 0) {
+ perf_trampoline_reset_state();
+ }
#endif
- return;
+ return 0;
}
int
diff --git a/contrib/tools/python3/Python/pylifecycle.c b/contrib/tools/python3/Python/pylifecycle.c
index 8cc6bd0fa78..8ba9b2bd006 100644
--- a/contrib/tools/python3/Python/pylifecycle.c
+++ b/contrib/tools/python3/Python/pylifecycle.c
@@ -1609,6 +1609,7 @@ finalize_remove_modules(PyObject *modules, int verbose)
PyObject *value = PyObject_GetItem(modules, key);
if (value == NULL) {
PyErr_FormatUnraisable("Exception ignored on removing modules");
+ Py_DECREF(key);
continue;
}
CLEAR_MODULE(key, value);
@@ -1929,7 +1930,6 @@ finalize_interp_clear(PyThreadState *tstate)
_PyArg_Fini();
_Py_ClearFileSystemEncoding();
_PyPerfTrampoline_Fini();
- _PyPerfTrampoline_FreeArenas();
}
finalize_interp_types(tstate->interp);
diff --git a/contrib/tools/python3/Python/pystate.c b/contrib/tools/python3/Python/pystate.c
index 2b1bff7f108..85c20ead488 100644
--- a/contrib/tools/python3/Python/pystate.c
+++ b/contrib/tools/python3/Python/pystate.c
@@ -1748,6 +1748,14 @@ PyThreadState_Clear(PyThreadState *tstate)
// Remove ourself from the biased reference counting table of threads.
_Py_brc_remove_thread(tstate);
+
+ // Flush the thread's local GC allocation count to the global count
+ // before the thread state is cleared, otherwise the count is lost.
+ _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
+ _Py_atomic_add_int(&tstate->interp->gc.generations[0].count,
+ (int)tstate_impl->gc.alloc_count);
+ tstate_impl->gc.alloc_count = 0;
+
#endif
// Merge our queue of pointers to be freed into the interpreter queue.
diff --git a/contrib/tools/python3/Python/sysmodule.c b/contrib/tools/python3/Python/sysmodule.c
index cf06943c7c8..782c595d2ab 100644
--- a/contrib/tools/python3/Python/sysmodule.c
+++ b/contrib/tools/python3/Python/sysmodule.c
@@ -2609,20 +2609,31 @@ PyAPI_FUNC(int) PyUnstable_CopyPerfMapFile(const char* parent_filename) {
}
char buf[4096];
PyThread_acquire_lock(perf_map_state.map_lock, 1);
- int fflush_result = 0, result = 0;
+ int result = 0;
while (1) {
size_t bytes_read = fread(buf, 1, sizeof(buf), from);
+ if (bytes_read == 0) {
+ if (ferror(from)) {
+ result = -1;
+ }
+ break;
+ }
+
size_t bytes_written = fwrite(buf, 1, bytes_read, perf_map_state.perf_map);
- fflush_result = fflush(perf_map_state.perf_map);
- if (fflush_result != 0 || bytes_read == 0 || bytes_written < bytes_read) {
+ if (bytes_written < bytes_read) {
result = -1;
- goto close_and_release;
+ break;
}
+
+ if (fflush(perf_map_state.perf_map) != 0) {
+ result = -1;
+ break;
+ }
+
if (bytes_read < sizeof(buf) && feof(from)) {
- goto close_and_release;
+ break;
}
}
-close_and_release:
fclose(from);
PyThread_release_lock(perf_map_state.map_lock);
return result;
diff --git a/contrib/tools/python3/Python/traceback.c b/contrib/tools/python3/Python/traceback.c
index f9840833716..81960a76927 100644
--- a/contrib/tools/python3/Python/traceback.c
+++ b/contrib/tools/python3/Python/traceback.c
@@ -356,6 +356,9 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *
npath = PyList_Size(syspath);
open = PyObject_GetAttr(io, &_Py_ID(open));
+ if (open == NULL) {
+ goto error;
+ }
for (i = 0; i < npath; i++) {
v = PyList_GetItem(syspath, i);
if (v == NULL) {
diff --git a/contrib/tools/python3/README.rst b/contrib/tools/python3/README.rst
index 879a54272b4..9694fc8a3d7 100644
--- a/contrib/tools/python3/README.rst
+++ b/contrib/tools/python3/README.rst
@@ -1,4 +1,4 @@
-This is Python version 3.13.11
+This is Python version 3.13.12
==============================
.. image:: https://github.com/python/cpython/workflows/Tests/badge.svg
diff --git a/contrib/tools/python3/bin/ya.make b/contrib/tools/python3/bin/ya.make
index d2f85b7c121..f14c11dbe6b 100644
--- a/contrib/tools/python3/bin/ya.make
+++ b/contrib/tools/python3/bin/ya.make
@@ -2,9 +2,9 @@
PY3_PROGRAM(python3)
-VERSION(3.13.11)
+VERSION(3.13.12)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.11.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.12.tar.gz)
LICENSE(Python-2.0)
diff --git a/contrib/tools/python3/lib2/py/ya.make b/contrib/tools/python3/lib2/py/ya.make
index a57bb8afe93..2544572470c 100644
--- a/contrib/tools/python3/lib2/py/ya.make
+++ b/contrib/tools/python3/lib2/py/ya.make
@@ -452,6 +452,7 @@ PY_SRCS(
pyclbr.py
pydoc.py
pydoc_data/__init__.py
+ pydoc_data/module_docs.py
pydoc_data/topics.py
queue.py
quopri.py
diff --git a/contrib/tools/python3/ya.make b/contrib/tools/python3/ya.make
index e319e83934f..028476ec8f6 100644
--- a/contrib/tools/python3/ya.make
+++ b/contrib/tools/python3/ya.make
@@ -2,9 +2,9 @@
LIBRARY()
-VERSION(3.13.11)
+VERSION(3.13.12)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.11.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.12.tar.gz)
LICENSE(Python-2.0)