Read contents of self as text.
+ Note: In Python 3.11 and later, this class is found in ``importlib.resources.abc``.
+
.. class:: TraversableResources
.. versionadded:: 3.9
+ Note: In Python 3.11 and later, this class is found in ``importlib.resources.abc``.
+
:mod:`importlib.resources` -- Resources
---------------------------------------
.. function:: files(package)
- Returns an :class:`importlib.resources.abc.Traversable` object
+ Returns an :class:`importlib.abc.Traversable` object
representing the resource container for the package (think directory)
and its resources (think files). A Traversable may contain other
containers (think subdirectories).
.. function:: as_file(traversable)
- Given a :class:`importlib.resources.abc.Traversable` object representing
+ Given a :class:`importlib.abc.Traversable` object representing
a file, typically from :func:`importlib.resources.files`, return
a context manager for use in a :keyword:`with` statement.
The context manager provides a :class:`pathlib.Path` object.
>>> _ = int('2' * 5432)
Traceback (most recent call last):
...
- ValueError: Exceeds the limit (4300) for integer string conversion: value has 5432 digits.
+ ValueError: Exceeds the limit (4300) for integer string conversion: value has 5432 digits; use sys.set_int_max_str_digits() to increase the limit.
>>> i = int('2' * 4300)
>>> len(str(i))
4300
>>> len(str(i_squared))
Traceback (most recent call last):
...
- ValueError: Exceeds the limit (4300) for integer string conversion: value has 8599 digits.
+ ValueError: Exceeds the limit (4300) for integer string conversion: value has 8599 digits; use sys.set_int_max_str_digits() to increase the limit.
>>> len(hex(i_squared))
7144
>>> assert int(hex(i_squared), base=16) == i*i # Hexadecimal is unlimited.
.. attribute:: output
Output of the child process if it was captured by :func:`run` or
- :func:`check_output`. Otherwise, ``None``.
+ :func:`check_output`. Otherwise, ``None``. This is always
+ :class:`bytes` when any output was captured regardless of the
+ ``text=True`` setting. It may remain ``None`` instead of ``b''``
+ when no output was observed.
.. attribute:: stdout
.. attribute:: stderr
Stderr output of the child process if it was captured by :func:`run`.
- Otherwise, ``None``.
+ Otherwise, ``None``. This is always :class:`bytes` when stderr output
+ was captured regardless of the ``text=True`` setting. It may remain
+ ``None`` instead of ``b''`` when no stderr output was observed.
.. versionadded:: 3.3
+------------------+-------+-------------------------+------------------------+
| :attr:`path` | 2 | Hierarchical path | empty string |
+------------------+-------+-------------------------+------------------------+
- | :attr:`params` | 3 | No longer used | always an empty string |
+ | :attr:`params` | 3 | Parameters for last | empty string |
+ | | | path element | |
+------------------+-------+-------------------------+------------------------+
| :attr:`query` | 4 | Query component | empty string |
+------------------+-------+-------------------------+------------------------+
/*--start constants--*/
#define PY_MAJOR_VERSION 3
#define PY_MINOR_VERSION 9
-#define PY_MICRO_VERSION 14
+#define PY_MICRO_VERSION 15
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.9.14"
+#define PY_VERSION "3.9.15"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
# -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Tue Sep 6 19:25:22 2022
+# Autogenerated by Sphinx on Tue Oct 11 16:45:32 2022
topics = {'assert': 'The "assert" statement\n'
'**********************\n'
'\n'
assert_python_failure('-X', 'int_max_str_digits', '-c', code)
assert_python_failure('-X', 'int_max_str_digits=foo', '-c', code)
assert_python_failure('-X', 'int_max_str_digits=100', '-c', code)
+ assert_python_failure('-X', 'int_max_str_digits', '-c', code,
+ PYTHONINTMAXSTRDIGITS='4000')
assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='foo')
assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='100')
self.assertRaises((MemoryError, OverflowError), mul, lst, n)
self.assertRaises((MemoryError, OverflowError), imul, lst, n)
+ def test_list_resize_overflow(self):
+ # gh-97616: test new_allocated * sizeof(PyObject*) overflow
+ # check in list_resize()
+ lst = [0] * 65
+ del lst[1:]
+ self.assertEqual(len(lst), 1)
+
+ size = ((2 ** (tuple.__itemsize__ * 8) - 1) // 2)
+ with self.assertRaises((MemoryError, OverflowError)):
+ lst * size
+ with self.assertRaises((MemoryError, OverflowError)):
+ lst *= size
+
def test_repr_large(self):
# Check the repr of large list objects
def check(n):
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
os.mkdir("dir", dir_fd=0)
+ def test_mkfifo(self):
+ self._verify_available("HAVE_MKFIFOAT")
+ if self.mac_ver >= (13, 0):
+ self.assertIn("HAVE_MKFIFOAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_MKFIFOAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.mkfifo("path", dir_fd=0)
+
+ def test_mknod(self):
+ self._verify_available("HAVE_MKNODAT")
+ if self.mac_ver >= (13, 0):
+ self.assertIn("HAVE_MKNODAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_MKNODAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.mknod("path", dir_fd=0)
+
def test_rename_replace(self):
self._verify_available("HAVE_RENAMEAT")
if self.mac_ver >= (10, 10):
def test_protocol(self):
for proto in PROTOCOLS:
- ctx = ssl.SSLContext(proto)
- self.assertEqual(ctx.protocol, proto)
+ if has_tls_protocol(proto):
+ with warnings_helper.check_warnings():
+ ctx = ssl.SSLContext(proto)
+ self.assertEqual(ctx.protocol, proto)
def test_ciphers(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
def test_session_stats(self):
for proto in PROTOCOLS:
- ctx = ssl.SSLContext(proto)
+ if not has_tls_protocol(proto):
+ continue
+ with warnings_helper.check_warnings():
+ ctx = ssl.SSLContext(proto)
self.assertEqual(ctx.session_stats(), {
'number': 0,
'connect': 0,
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
self._assert_context_options(ctx)
- ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
- cert_reqs=ssl.CERT_REQUIRED,
- check_hostname=True)
- self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
- self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
- self.assertTrue(ctx.check_hostname)
- self._assert_context_options(ctx)
+ with warnings_helper.check_warnings():
+ ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
+ cert_reqs=ssl.CERT_REQUIRED,
+ check_hostname=True)
+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
+ self.assertTrue(ctx.check_hostname)
+ self._assert_context_options(ctx)
ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Python News
+++++++++++
+What's New in Python 3.9.15 final?
+==================================
+
+*Release date: 2022-10-11*
+
+Security
+--------
+
+- gh-issue-97616: Fix multiplying a list by an integer (``list *= int``):
+ detect the integer overflow when the new allocated length is close to the
+ maximum size. Issue reported by Jordan Limor. Patch by Victor Stinner.
+
+- gh-issue-97612: Fix a shell code injection vulnerability in the
+ ``get-remote-certificate.py`` example script. The script no longer uses a
+ shell to run ``openssl`` commands. Issue reported and initial fix by Caleb
+ Shortt. Patch by Victor Stinner.
+
+Core and Builtins
+-----------------
+
+- gh-issue-96848: Fix command line parsing: reject :option:`-X
+ int_max_str_digits <-X>` option with no value (invalid) when the
+ :envvar:`PYTHONINTMAXSTRDIGITS` environment variable is set to a valid
+ limit. Patch by Victor Stinner.
+
+- gh-issue-95778: When :exc:`ValueError` is raised if an integer is larger
+ than the limit, mention the :func:`sys.set_int_max_str_digits` function in
+ the error message. Patch by Victor Stinner.
+
+Library
+-------
+
+- gh-issue-97005: Update bundled libexpat to 2.4.9
+
+Windows
+-------
+
+- gh-issue-96577: Fixes a potential buffer overrun in :mod:`msilib`.
+
+macOS
+-----
+
+- gh-issue-97897: The macOS 13 SDK includes support for the ``mkfifoat`` and
+ ``mknodat`` system calls. Using the ``dir_fd`` option with either
+ :func:`os.mkfifo` or :func:`os.mknod` could result in a segfault if
+ cpython is built with the macOS 13 SDK but run on an earlier version of
+ macOS. Prevent this by adding runtime support for detection of these
+ system calls ("weaklinking") as is done for other newer syscalls on macOS.
+
+
What's New in Python 3.9.14 final?
==================================
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
-Copyright (c) 2001-2019 Expat maintainers
+Copyright (c) 2001-2022 Expat maintainers
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
*/
#define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 4
-#define XML_MICRO_VERSION 7
+#define XML_MICRO_VERSION 9
#ifdef __cplusplus
}
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
- Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
Licensed under the MIT license:
#include <limits.h> // ULONG_MAX
-#if defined(_WIN32) && ! defined(__USE_MINGW_ANSI_STDIO)
+#if defined(_WIN32) \
+ && (! defined(__USE_MINGW_ANSI_STDIO) \
+ || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0))
# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
# if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
* if this code is included and compiled as C++; related GCC warning is:
* warning: use of C++11 long long integer constant [-Wlong-long]
*/
-#define _SIP_ULL(high, low) (((uint64_t)high << 32) | low)
+#define _SIP_ULL(high, low) ((((uint64_t)high) << 32) | (low))
#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
-/* fcb1a62fefa945567301146eb98e3ad3413e823a41c4378e84e8b6b6f308d824 (2.4.7+)
+/* 90815a2b2c80c03b2b889fe1d427bb2b9e3282aa065e42784e001db4f23de324 (2.4.9+)
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
Copyright (c) 2016 Gustavo Grieco <gustavo.grieco@imag.fr>
Copyright (c) 2016 Pascal Cuoq <cuoq@trust-in-soft.com>
Copyright (c) 2016 Ed Schouten <ed@nuxi.nl>
- Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk>
+ Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2017 Václav Slavík <vaclav@slavik.io>
Copyright (c) 2017 Viktor Szakats <commit@vsz.me>
Copyright (c) 2017 Chanho Park <chanho61.park@samsung.com>
const XML_Char *storedEncName = NULL;
const ENCODING *newEncoding = NULL;
const char *version = NULL;
- const char *versionend;
+ const char *versionend = NULL;
const XML_Char *storedversion = NULL;
int standalone = -1;
{
parser->m_processor = contentProcessor;
/* see externalEntityContentProcessor vs contentProcessor */
- return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
- s, end, nextPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer,
- XML_ACCOUNT_DIRECT);
+ result = doContent(parser, parser->m_parentParser ? 1 : 0,
+ parser->m_encoding, s, end, nextPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
+ XML_ACCOUNT_DIRECT);
+ if (result == XML_ERROR_NONE) {
+ if (! storeRawNames(parser))
+ return XML_ERROR_NO_MEMORY;
+ }
+ return result;
}
}
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
Copyright (c) 2021 Dong-hee Na <donghee.na@python.org>
+ Copyright (c) 2022 Martin Ettl <ettl.martin78@googlemail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
}
#else
/* c is an ASCII character */
-# define CHAR_MATCHES(enc, p, c) (*(p) == c)
+# define CHAR_MATCHES(enc, p, c) (*(p) == (c))
#endif
#define PREFIX(ident) normal_##ident
((p)[1] == 0 ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
: unicode_byte_type((p)[1], (p)[0]))
#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
-#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c))
#define LITTLE2_IS_NAME_CHAR_MINBPC(p) \
UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) \
? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
: unicode_byte_type((p)[0], (p)[1]))
#define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
-#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c))
#define BIG2_IS_NAME_CHAR_MINBPC(p) \
UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p) \
Copyright (c) 2018 Anton Maklakov <antmak.pub@gmail.com>
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
Copyright (c) 2020 Boris Kolpackov <boris@codesynthesis.com>
+ Copyright (c) 2022 Martin Ettl <ettl.martin78@googlemail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
# define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
case BT_LEAD##n: \
- if (end - ptr < n) \
+ if ((end) - (ptr) < (n)) \
return XML_TOK_PARTIAL_CHAR; \
if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \
*nextTokPtr = ptr; \
# define PREFIX(ident) ident
# endif
-# define HAS_CHARS(enc, ptr, end, count) (end - ptr >= count * MINBPC(enc))
+# define HAS_CHARS(enc, ptr, end, count) \
+ ((end) - (ptr) >= ((count)*MINBPC(enc)))
# define HAS_CHAR(enc, ptr, end) HAS_CHARS(enc, ptr, end, 1)
# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
+# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
+# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
# define HAVE_FUTIMENS_RUNTIME 1
# define HAVE_UTIMENSAT_RUNTIME 1
# define HAVE_PWRITEV_RUNTIME 1
+# define HAVE_MKFIFOAT_RUNTIME 1
+# define HAVE_MKNODAT_RUNTIME 1
#endif
{
int result;
int async_err = 0;
+#ifdef HAVE_MKFIFOAT
+ int mkfifoat_unavailable = 0;
+#endif
do {
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_MKFIFOAT
- if (dir_fd != DEFAULT_DIR_FD)
- result = mkfifoat(dir_fd, path->narrow, mode);
- else
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_MKFIFOAT_RUNTIME) {
+ result = mkfifoat(dir_fd, path->narrow, mode);
+
+ } else {
+ mkfifoat_unavailable = 1;
+ result = 0;
+ }
+ } else
#endif
result = mkfifo(path->narrow, mode);
Py_END_ALLOW_THREADS
} while (result != 0 && errno == EINTR &&
!(async_err = PyErr_CheckSignals()));
+
+#ifdef HAVE_MKFIFOAT
+ if (mkfifoat_unavailable) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result != 0)
return (!async_err) ? posix_error() : NULL;
{
int result;
int async_err = 0;
+#ifdef HAVE_MKNODAT
+ int mknodat_unavailable = 0;
+#endif
do {
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_MKNODAT
- if (dir_fd != DEFAULT_DIR_FD)
- result = mknodat(dir_fd, path->narrow, mode, device);
- else
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_MKNODAT_RUNTIME) {
+ result = mknodat(dir_fd, path->narrow, mode, device);
+
+ } else {
+ mknodat_unavailable = 1;
+ result = 0;
+ }
+ } else
#endif
result = mknod(path->narrow, mode, device);
Py_END_ALLOW_THREADS
} while (result != 0 && errno == EINTR &&
!(async_err = PyErr_CheckSignals()));
+#ifdef HAVE_MKNODAT
+ if (mknodat_unavailable) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
if (result != 0)
return (!async_err) ? posix_error() : NULL;
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
#endif
+#ifdef HAVE_MKFIFOAT
+PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
+#endif
+
+#ifdef HAVE_MKNODAT
+PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
+#endif
+
#ifdef HAVE_RENAMEAT
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
#endif
#endif
#ifdef HAVE_MKFIFOAT
- { "HAVE_MKFIFOAT", NULL },
+ { "HAVE_MKFIFOAT", probe_mkfifoat },
#endif
#ifdef HAVE_MKNODAT
- { "HAVE_MKNODAT", NULL },
+ { "HAVE_MKNODAT", probe_mknodat },
#endif
#ifdef HAVE_OPENAT
if (newsize == 0)
new_allocated = 0;
- num_allocated_bytes = new_allocated * sizeof(PyObject *);
- items = (PyObject **)PyMem_Realloc(self->ob_item, num_allocated_bytes);
+ if (new_allocated <= (size_t)PY_SSIZE_T_MAX / sizeof(PyObject *)) {
+ num_allocated_bytes = new_allocated * sizeof(PyObject *);
+ items = (PyObject **)PyMem_Realloc(self->ob_item, num_allocated_bytes);
+ }
+ else {
+ // integer overflow
+ items = NULL;
+ }
if (items == NULL) {
PyErr_NoMemory();
return -1;
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
-#define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d) for integer string conversion: value has %zd digits"
-#define _MAX_STR_DIGITS_ERROR_FMT_TO_STR "Exceeds the limit (%d) for integer string conversion"
+#define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d) for integer string conversion: value has %zd digits; use sys.set_int_max_str_digits() to increase the limit"
+#define _MAX_STR_DIGITS_ERROR_FMT_TO_STR "Exceeds the limit (%d) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit"
static PyObject *
get_small_int(sdigit ival)
int code;
char buf[2000];
char *res = buf;
- DWORD size = sizeof(buf);
+ DWORD size = Py_ARRAY_LENGTH(buf);
MSIHANDLE err = MsiGetLastErrorRecord();
if (err == 0) {
unsigned int status;
WCHAR buf[2000];
WCHAR *res = buf;
- DWORD size = sizeof(buf);
+ DWORD size = Py_ARRAY_LENGTH(buf);
PyObject* string;
if (!PyArg_ParseTuple(args, "I:GetString", &field))
config_init_int_max_str_digits(PyConfig *config)
{
int maxdigits;
- int valid = 0;
const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS");
if (env) {
+ int valid = 0;
if (!_Py_str_to_int(env, &maxdigits)) {
valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
}
const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits");
if (xoption) {
const wchar_t *sep = wcschr(xoption, L'=');
+ int valid = 0;
if (sep) {
if (!config_wstr_to_int(sep + 1, &maxdigits)) {
valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
-This is Python version 3.9.14
+This is Python version 3.9.15
=============================
.. image:: https://travis-ci.org/python/cpython.svg?branch=3.9
def fetch_server_certificate (host, port):
def subproc(cmd):
- from subprocess import Popen, PIPE, STDOUT
- proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
+ from subprocess import Popen, PIPE, STDOUT, DEVNULL
+ proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, stdin=DEVNULL)
status = proc.wait()
output = proc.stdout.read()
return status, output
fp.write(m.group(1) + b"\n")
try:
tn2 = (outfile or tempfile.mktemp())
- status, output = subproc(r'openssl x509 -in "%s" -out "%s"' %
- (tn, tn2))
+ cmd = ['openssl', 'x509', '-in', tn, '-out', tn2]
+ status, output = subproc(cmd)
if status != 0:
raise RuntimeError('OpenSSL x509 failed with status %s and '
'output: %r' % (status, output))
finally:
os.unlink(tn)
- if sys.platform.startswith("win"):
- tfile = tempfile.mktemp()
- with open(tfile, "w") as fp:
- fp.write("quit\n")
- try:
- status, output = subproc(
- 'openssl s_client -connect "%s:%s" -showcerts < "%s"' %
- (host, port, tfile))
- finally:
- os.unlink(tfile)
- else:
- status, output = subproc(
- 'openssl s_client -connect "%s:%s" -showcerts < /dev/null' %
- (host, port))
+ cmd = ['openssl', 's_client', '-connect', '%s:%s' % (host, port), '-showcerts']
+ status, output = subproc(cmd)
+
if status != 0:
raise RuntimeError('OpenSSL connect failed with status %s and '
'output: %r' % (status, output))