diff options
| author | shadchin <[email protected]> | 2026-02-07 19:56:35 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2026-02-07 20:23:53 +0300 |
| commit | 19d43a3e6fb4cb8ea11747d7d7bca7a3542fbb44 (patch) | |
| tree | 0b1418938140a0b6470953bef6069454ffdf1bd0 | |
| parent | 0879409bfc0891ab8103828a3bdbf0e960475fec (diff) | |
Update Python 3 to 3.13.12
commit_hash:71d3efea437a769b2b7910d196120bb02587046e
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) |
