Imported Upstream version 3.8.5 upstream/3.8.5
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 9 Dec 2020 00:40:18 +0000 (09:40 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 9 Dec 2020 00:40:18 +0000 (09:40 +0900)
29 files changed:
Doc/library/asyncio-task.rst
Doc/library/decimal.rst
Doc/library/multiprocessing.rst
Doc/library/unittest.mock.rst
Doc/library/urllib.parse.rst
Doc/tutorial/classes.rst
Doc/whatsnew/3.8.rst
Include/patchlevel.h
Lib/asyncio/tasks.py
Lib/http/client.py
Lib/idlelib/NEWS.txt
Lib/idlelib/iomenu.py
Lib/pydoc_data/topics.py
Lib/tarfile.py
Lib/test/pickletester.py
Lib/test/recursion.tar [new file with mode: 0644]
Lib/test/test_descr.py
Lib/test/test_httplib.py
Lib/test/test_site.py
Lib/test/test_tarfile.py
Mac/BuildScript/build-installer.py
Misc/NEWS
Modules/_decimal/_decimal.c
Modules/_pickle.c
Modules/overlapped.c
Objects/typeobject.c
PC/getpathp.c
Python/thread_pthread.h
README.rst

index 00ce5d4b72bdd34a403fb247a904be6e0a792c85..c96dde2dde9254f7b4db1ad2ee9790169d3d16e9 100644 (file)
@@ -385,6 +385,14 @@ Running Tasks Concurrently
       #     Task C: Compute factorial(4)...
       #     Task C: factorial(4) = 24
 
+   .. note::
+      If *return_exceptions* is False, cancelling gather() after it
+      has been marked done won't cancel any submitted awaitables.
+      For instance, gather can be marked done after propagating an
+      exception to the caller, therefore, calling ``gather.cancel()``
+      after catching an exception (raised by one of the awaitables) from
+      gather won't cancel any other awaitables.
+
    .. versionchanged:: 3.7
       If the *gather* itself is cancelled, the cancellation is
       propagated regardless of *return_exceptions*.
index 8169bd358c70172035e67085a53e6890b3ef056c..38173f18ca66020a1ee5e7a12cb2e2a3ac2bb645 100644 (file)
@@ -1357,6 +1357,9 @@ In addition to the three supplied contexts, new contexts can be created with the
       The rounding mode of the context is used. Results are always correctly-rounded
       in the Python version.
 
+      ``Decimal(0) ** Decimal(0)`` results in ``InvalidOperation``, and if ``InvalidOperation``
+      is not trapped, then results in ``Decimal('NaN')``.
+
       .. versionchanged:: 3.3
          The C module computes :meth:`power` in terms of the correctly-rounded
          :meth:`exp` and :meth:`ln` functions. The result is well-defined but
index ec9521f1fb4a0cc7229bb6332508b63e946d987d..bb3ee87a4403a047c41c320ec77ead083de0b357 100644 (file)
@@ -2163,7 +2163,8 @@ with the :class:`Pool` class.
 
    .. method:: apply_async(func[, args[, kwds[, callback[, error_callback]]]])
 
-      A variant of the :meth:`apply` method which returns a result object.
+      A variant of the :meth:`apply` method which returns a
+      :class:`~multiprocessing.pool.AsyncResult` object.
 
       If *callback* is specified then it should be a callable which accepts a
       single argument.  When the result becomes ready *callback* is applied to
@@ -2193,7 +2194,8 @@ with the :class:`Pool` class.
 
    .. method:: map_async(func, iterable[, chunksize[, callback[, error_callback]]])
 
-      A variant of the :meth:`.map` method which returns a result object.
+      A variant of the :meth:`.map` method which returns a
+      :class:`~multiprocessing.pool.AsyncResult` object.
 
       If *callback* is specified then it should be a callable which accepts a
       single argument.  When the result becomes ready *callback* is applied to
index e92f5545d3eb0573da999ce88a1c2087162a6da8..34966b38a0dcd8fbc3fe3cf4010ed5d7982cec29 100644 (file)
@@ -647,6 +647,9 @@ the *new_callable* argument to :func:`patch`.
         arguments and make more complex assertions. See
         :ref:`calls as tuples <calls-as-tuples>`.
 
+        .. versionchanged:: 3.8
+           Added ``args`` and ``kwargs`` properties.
+
 
     .. attribute:: call_args_list
 
index 52f98ef39fcc3ffc526938cfcf63a77672f831e0..25e5cc1a6ce0b27356be08875cb1533932adf95d 100644 (file)
@@ -68,15 +68,15 @@ or on combining URL components into a URL string.
    .. doctest::
       :options: +NORMALIZE_WHITESPACE
 
-       >>> from urllib.parse import urlparse
-       >>> urlparse('//www.cwi.nl:80/%7Eguido/Python.html')
-       ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
+      >>> from urllib.parse import urlparse
+      >>> urlparse('//www.cwi.nl:80/%7Eguido/Python.html')
+      ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
                   params='', query='', fragment='')
-       >>> urlparse('www.cwi.nl/%7Eguido/Python.html')
-       ParseResult(scheme='', netloc='', path='www.cwi.nl/%7Eguido/Python.html',
+      >>> urlparse('www.cwi.nl/%7Eguido/Python.html')
+      ParseResult(scheme='', netloc='', path='www.cwi.nl/%7Eguido/Python.html',
                   params='', query='', fragment='')
-       >>> urlparse('help/Python.html')
-       ParseResult(scheme='', netloc='', path='help/Python.html', params='',
+      >>> urlparse('help/Python.html')
+      ParseResult(scheme='', netloc='', path='help/Python.html', params='',
                   query='', fragment='')
 
    The *scheme* argument gives the default addressing scheme, to be
@@ -138,14 +138,14 @@ or on combining URL components into a URL string.
    .. doctest::
       :options: +NORMALIZE_WHITESPACE
 
-       >>> from urllib.parse import urlparse
-       >>> u = urlparse('//www.cwi.nl:80/%7Eguido/Python.html')
-       >>> u
-       ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
-                   params='', query='', fragment='')
-       >>> u._replace(scheme='http')
-       ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
-                   params='', query='', fragment='')
+      >>> from urllib.parse import urlparse
+      >>> u = urlparse('//www.cwi.nl:80/%7Eguido/Python.html')
+      >>> u
+      ParseResult(scheme='', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
+                  params='', query='', fragment='')
+      >>> u._replace(scheme='http')
+      ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
+                  params='', query='', fragment='')
 
 
    .. versionchanged:: 3.2
index 250d2a9ddb416b47e05d5e4eaf5710f3a2252927..685552f99f440e9da8bdd6fb5e02ef50037850fa 100644 (file)
@@ -114,8 +114,8 @@ accessible.  "Directly accessible" here means that an unqualified reference to a
 name attempts to find the name in the namespace.
 
 Although scopes are determined statically, they are used dynamically. At any
-time during execution, At any time during execution, there are 3 or 4 nested
-scopes whose namespaces are directly accessible:
+time during execution, there are 3 or 4 nested scopes whose namespaces are
+directly accessible:
 
 * the innermost scope, which is searched first, contains the local names
 * the scopes of any enclosing functions, which are searched starting with the
index d2db5bff5afcf5871cdf55bc1a7de6f0905d3267..475e3ab964312091871296ddfea72ba3f54d05af 100644 (file)
@@ -648,7 +648,8 @@ loop on every invocation:
 (Contributed by Yury Selivanov in :issue:`37028`.)
 
 The exception :class:`asyncio.CancelledError` now inherits from
-:class:`BaseException` rather than :class:`Exception`.
+:class:`BaseException` rather than :class:`Exception` and no longer inherits
+from :class:`concurrent.futures.CancelledError`.
 (Contributed by Yury Selivanov in :issue:`32528`.)
 
 On Windows, the default event loop is now :class:`~asyncio.ProactorEventLoop`.
@@ -1953,7 +1954,8 @@ Changes in the Python API
   (Contributed by Anthony Sottile in :issue:`36264`.)
 
 * The exception :class:`asyncio.CancelledError` now inherits from
-  :class:`BaseException` rather than :class:`Exception`.
+  :class:`BaseException` rather than :class:`Exception` and no longer inherits
+  from :class:`concurrent.futures.CancelledError`.
   (Contributed by Yury Selivanov in :issue:`32528`.)
 
 * The function :func:`asyncio.wait_for` now correctly waits for cancellation
index 41901a585f84d0ba04ac73db32705a0db4b9b9fd..25fc2d3a7adcad97e2162faf8993bd068bcbcbf7 100644 (file)
 /*--start constants--*/
 #define PY_MAJOR_VERSION        3
 #define PY_MINOR_VERSION        8
-#define PY_MICRO_VERSION        4
+#define PY_MICRO_VERSION        5
 #define PY_RELEASE_LEVEL        PY_RELEASE_LEVEL_FINAL
 #define PY_RELEASE_SERIAL       0
 
 /* Version as a string */
-#define PY_VERSION              "3.8.4"
+#define PY_VERSION              "3.8.5"
 /*--end constants--*/
 
 /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
index 38d982716d46ad1b5b37c8d6b03185d0274eec31..66e81f9200a36d8478790bb0fe8f8bda2852fb46 100644 (file)
@@ -736,6 +736,13 @@ def gather(*coros_or_futures, loop=None, return_exceptions=False):
     the outer Future is *not* cancelled in this case.  (This is to
     prevent the cancellation of one child to cause other children to
     be cancelled.)
+
+    If *return_exceptions* is False, cancelling gather() after it
+    has been marked done won't cancel any submitted awaitables.
+    For instance, gather can be marked done after propagating an
+    exception to the caller, therefore, calling ``gather.cancel()``
+    after catching an exception (raised by one of the awaitables) from
+    gather won't cancel any other awaitables.
     """
     if not coros_or_futures:
         if loop is None:
index 019380a72031810c7ca53a750a3bf21a89c8238c..c2ad0471bfee50ec85ce239dd8fe7584782716d2 100644 (file)
@@ -147,6 +147,10 @@ _contains_disallowed_url_pchar_re = re.compile('[\x00-\x20\x7f]')
 #  _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$")
 # We are more lenient for assumed real world compatibility purposes.
 
+# These characters are not allowed within HTTP method names
+# to prevent http header injection.
+_contains_disallowed_method_pchar_re = re.compile('[\x00-\x1f]')
+
 # We always set the Content-Length header for these methods because some
 # servers will otherwise respond with a 411
 _METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'}
@@ -1087,6 +1091,8 @@ class HTTPConnection:
         else:
             raise CannotSendRequest(self.__state)
 
+        self._validate_method(method)
+
         # Save the method for use later in the response phase
         self._method = method
 
@@ -1177,6 +1183,15 @@ class HTTPConnection:
         # ASCII also helps prevent CVE-2019-9740.
         return request.encode('ascii')
 
+    def _validate_method(self, method):
+        """Validate a method name for putrequest."""
+        # prevent http header injection
+        match = _contains_disallowed_method_pchar_re.search(method)
+        if match:
+            raise ValueError(
+                    f"method can't contain control characters. {method!r} "
+                    f"(found at least {match.group()!r})")
+
     def _validate_path(self, url):
         """Validate a url for putrequest."""
         # Prevent CVE-2019-9740.
index b43c6d3a64cfd689d25cb6b5de85090a41076301..ddc1e22e23ed4865125cae00f13c5ad13a938e78 100644 (file)
@@ -1,8 +1,15 @@
-What's New in IDLE 3.8.4
-Released on 2020-07-03?
+What's New in IDLE 3.8.5
+Released on 2020-07-20
 ======================================
 
 
+bpo-41300: Save files with non-ascii chars.  Fix regression in
+3.9.0b4 and 3.8.4.
+
+What's New in IDLE 3.8.4
+Released on 2020-06-30
+======================================
+
 bpo-37765: Add keywords to module name completion list.  Rewrite
 Completions section of IDLE doc.
 
index 7641d866858a1db2229e05951791b0cf494425b8..74ebefd4208f78fac6eede4f1aa25159566a1ef1 100644 (file)
@@ -1,3 +1,4 @@
+import io
 import os
 import shlex
 import sys
index d4473aaa6e63c9e48075db3c291300bce74958dd..68346572bc3ee0aa49fe4b4a519a1e493690ac1d 100644 (file)
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Mon Jul 13 13:47:56 2020
+# Autogenerated by Sphinx on Mon Jul 20 14:14:54 2020
 topics = {'assert': 'The "assert" statement\n'
            '**********************\n'
            '\n'
index d31b9cbb51d654631672b10baf650bb9bbc38fd5..7a69e1b1aa54404ebb309073a950398926cf393f 100755 (executable)
@@ -1241,6 +1241,8 @@ class TarInfo(object):
 
             length, keyword = match.groups()
             length = int(length)
+            if length == 0:
+                raise InvalidHeaderError("invalid header")
             value = buf[match.end(2) + 1:match.start(1) + length - 1]
 
             # Normally, we could just use "utf-8" as the encoding and "strict"
index 9401043d78d18b122ca9845b322298b35f0a0afa..ff7bbb0c8a9bff0eeac14400acef60004b76584f 100644 (file)
@@ -1170,6 +1170,24 @@ class AbstractUnpickleTests(unittest.TestCase):
             self.assertIs(type(unpickled), collections.UserDict)
             self.assertEqual(unpickled, collections.UserDict({1: 2}))
 
+    def test_bad_reduce(self):
+        self.assertEqual(self.loads(b'cbuiltins\nint\n)R.'), 0)
+        self.check_unpickling_error(TypeError, b'N)R.')
+        self.check_unpickling_error(TypeError, b'cbuiltins\nint\nNR.')
+
+    def test_bad_newobj(self):
+        error = (pickle.UnpicklingError, TypeError)
+        self.assertEqual(self.loads(b'cbuiltins\nint\n)\x81.'), 0)
+        self.check_unpickling_error(error, b'cbuiltins\nlen\n)\x81.')
+        self.check_unpickling_error(error, b'cbuiltins\nint\nN\x81.')
+
+    def test_bad_newobj_ex(self):
+        error = (pickle.UnpicklingError, TypeError)
+        self.assertEqual(self.loads(b'cbuiltins\nint\n)}\x92.'), 0)
+        self.check_unpickling_error(error, b'cbuiltins\nlen\n)}\x92.')
+        self.check_unpickling_error(error, b'cbuiltins\nint\nN}\x92.')
+        self.check_unpickling_error(error, b'cbuiltins\nint\n)N\x92.')
+
     def test_bad_stack(self):
         badpickles = [
             b'.',                       # STOP
diff --git a/Lib/test/recursion.tar b/Lib/test/recursion.tar
new file mode 100644 (file)
index 0000000..b823725
Binary files /dev/null and b/Lib/test/recursion.tar differ
index c4d900a8c1bcb918f76a16a79b46236163b849d0..18397a86b14c5e57a5e392ff7f5351e41e46d65c 100644 (file)
@@ -4315,6 +4315,42 @@ order (MRO) for bases """
         else:
             self.fail("Carlo Verre __delattr__ succeeded!")
 
+    def test_carloverre_multi_inherit_valid(self):
+        class A(type):
+            def __setattr__(cls, key, value):
+                type.__setattr__(cls, key, value)
+
+        class B:
+            pass
+
+        class C(B, A):
+            pass
+
+        obj = C('D', (object,), {})
+        try:
+            obj.test = True
+        except TypeError:
+            self.fail("setattr through direct base types should be legal")
+
+    def test_carloverre_multi_inherit_invalid(self):
+        class A(type):
+            def __setattr__(cls, key, value):
+                object.__setattr__(cls, key, value)  # this should fail!
+
+        class B:
+            pass
+
+        class C(B, A):
+            pass
+
+        obj = C('D', (object,), {})
+        try:
+            obj.test = True
+        except TypeError:
+            pass
+        else:
+            self.fail("setattr through indirect base types should be rejected")
+
     def test_weakref_segfault(self):
         # Testing weakref segfault...
         # SF 742911
index 8f0e27a1fb83685b73298702ab53a4c57accfd5b..5a5fcecbc9c15d967363c58fbf33f51d2c6c8560 100644 (file)
@@ -364,6 +364,28 @@ class HeaderTests(TestCase):
         self.assertEqual(lines[3], "header: Second: val2")
 
 
+class HttpMethodTests(TestCase):
+    def test_invalid_method_names(self):
+        methods = (
+            'GET\r',
+            'POST\n',
+            'PUT\n\r',
+            'POST\nValue',
+            'POST\nHOST:abc',
+            'GET\nrHost:abc\n',
+            'POST\rRemainder:\r',
+            'GET\rHOST:\n',
+            '\nPUT'
+        )
+
+        for method in methods:
+            with self.assertRaisesRegex(
+                    ValueError, "method can't contain control characters"):
+                conn = client.HTTPConnection('example.com')
+                conn.sock = FakeSocket(None)
+                conn.request(method=method, url="/")
+
+
 class TransferEncodingTest(TestCase):
     expected_body = b"It's just a flesh wound"
 
index 9a047fd4669d12bc58c4bb10e4885561b51bca90..01008656bdd759246627182ccbe33fea9b048c24 100644 (file)
@@ -581,12 +581,19 @@ class StartupImportTests(unittest.TestCase):
 @unittest.skipUnless(sys.platform == 'win32', "only supported on Windows")
 class _pthFileTests(unittest.TestCase):
 
-    def _create_underpth_exe(self, lines):
+    def _create_underpth_exe(self, lines, exe_pth=True):
+        import _winapi
         temp_dir = tempfile.mkdtemp()
         self.addCleanup(test.support.rmtree, temp_dir)
         exe_file = os.path.join(temp_dir, os.path.split(sys.executable)[1])
+        dll_src_file = _winapi.GetModuleFileName(sys.dllhandle)
+        dll_file = os.path.join(temp_dir, os.path.split(dll_src_file)[1])
         shutil.copy(sys.executable, exe_file)
-        _pth_file = os.path.splitext(exe_file)[0] + '._pth'
+        shutil.copy(dll_src_file, dll_file)
+        if exe_pth:
+            _pth_file = os.path.splitext(exe_file)[0] + '._pth'
+        else:
+            _pth_file = os.path.splitext(dll_file)[0] + '._pth'
         with open(_pth_file, 'w') as f:
             for line in lines:
                 print(line, file=f)
@@ -654,5 +661,30 @@ class _pthFileTests(unittest.TestCase):
         self.assertTrue(rc, "sys.path is incorrect")
 
 
+    def test_underpth_dll_file(self):
+        libpath = os.path.dirname(os.path.dirname(encodings.__file__))
+        exe_prefix = os.path.dirname(sys.executable)
+        exe_file = self._create_underpth_exe([
+            'fake-path-name',
+            *[libpath for _ in range(200)],
+            '',
+            '# comment',
+            'import site'
+        ], exe_pth=False)
+        sys_prefix = os.path.dirname(exe_file)
+        env = os.environ.copy()
+        env['PYTHONPATH'] = 'from-env'
+        env['PATH'] = '{};{}'.format(exe_prefix, os.getenv('PATH'))
+        rc = subprocess.call([exe_file, '-c',
+            'import sys; sys.exit(not sys.flags.no_site and '
+            '%r in sys.path and %r in sys.path and %r not in sys.path and '
+            'all("\\r" not in p and "\\n" not in p for p in sys.path))' % (
+                os.path.join(sys_prefix, 'fake-path-name'),
+                libpath,
+                os.path.join(sys_prefix, 'from-env'),
+            )], env=env)
+        self.assertTrue(rc, "sys.path is incorrect")
+
+
 if __name__ == "__main__":
     unittest.main()
index 15324a4e48819ef67b8c3dd2916bef455c62af0f..b512168d6ea87017d1acd602f281d25b681d4054 100644 (file)
@@ -397,6 +397,13 @@ class CommonReadTest(ReadTest):
                 with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"):
                     tar.extractfile(t).read()
 
+    def test_length_zero_header(self):
+        # bpo-39017 (CVE-2019-20907): reading a zero-length header should fail
+        # with an exception
+        with self.assertRaisesRegex(tarfile.ReadError, "file could not be opened successfully"):
+            with tarfile.open(support.findfile('recursion.tar')) as tar:
+                pass
+
 class MiscReadTestBase(CommonReadTest):
     def requires_name_attribute(self):
         pass
index 4fab4882efaeb63b6ba6bde926c3a490f8598970..a58b922ce30b8363f208241ea6d1bb97d5f16112 100755 (executable)
@@ -307,9 +307,9 @@ def library_recipes():
                   ),
           ),
           dict(
-              name="SQLite 3.32.2",
-              url="https://sqlite.org/2020/sqlite-autoconf-3320200.tar.gz",
-              checksum='eb498918a33159cdf8104997aad29e83',
+              name="SQLite 3.32.3",
+              url="https://sqlite.org/2020/sqlite-autoconf-3320300.tar.gz",
+              checksum='2e3911a3c15e85c2f2d040154bbe5ce3',
               extra_cflags=('-Os '
                             '-DSQLITE_ENABLE_FTS5 '
                             '-DSQLITE_ENABLE_FTS4 '
index 7486b79750a6e4f63f7aacc75ba3d873d5747a2b..c7c412e33304464ad15e986d34edb40576697322 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -2,6 +2,61 @@
 Python News
 +++++++++++
 
+What's New in Python 3.8.5 final?
+=================================
+
+*Release date: 2020-07-20*
+
+Security
+--------
+
+- bpo-41304: Fixes `python3x._pth` being ignored on Windows, caused by the
+  fix for :issue:`29778` (CVE-2020-15801).
+
+- bpo-39603: Prevent http header injection by rejecting control characters
+  in http.client.putrequest(...).
+
+Core and Builtins
+-----------------
+
+- bpo-41295: Resolve a regression in CPython 3.8.4 where defining
+  "__setattr__" in a multi-inheritance setup and calling up the hierarchy
+  chain could fail if builtins/extension types were involved in the base
+  types.
+
+Library
+-------
+
+- bpo-41288: Unpickling invalid NEWOBJ_EX opcode with the C implementation
+  raises now UnpicklingError instead of crashing.
+
+- bpo-39017: Avoid infinite loop when reading specially crafted TAR files
+  using the tarfile module (CVE-2019-20907).
+
+Documentation
+-------------
+
+- bpo-37703: Updated Documentation to comprehensively elaborate on the
+  behaviour of gather.cancel()
+
+Build
+-----
+
+- bpo-41302: Enable building Python 3.8 with libmpdec-2.5.0 to ease
+  maintenance for Linux distributions. Patch by Felix Yan.
+
+macOS
+-----
+
+- bpo-40741: Update macOS installer to use SQLite 3.32.3.
+
+IDLE
+----
+
+- bpo-41300: Save files with non-ascii chars. Fix regression released in
+  3.9.0b4 and 3.8.4.
+
+
 What's New in Python 3.8.4 final?
 =================================
 
index df7c6e254bcf29f863886dc5038c4dcc215c6f5f..eb1f1a01feeca8374b1e67adb045e8b1953e86f1 100644 (file)
 
 #define BOUNDS_CHECK(x, MIN, MAX) x = (x < MIN || MAX < x) ? MAX : x
 
+#ifndef UNUSED
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+  #define UNUSED __attribute__((unused))
+#else
+  #define UNUSED
+#endif
+#endif
 
 /* _Py_DEC_MINALLOC >= MPD_MINALLOC */
 #define _Py_DEC_MINALLOC 4
index 55affb2c7c47968fd6624a3eb17ee937ca52f776..42ce62fc7cdf4e18e3af6d18a256e1df15b96221 100644 (file)
@@ -5988,23 +5988,30 @@ load_newobj_ex(UnpicklerObject *self)
     }
 
     if (!PyType_Check(cls)) {
-        Py_DECREF(kwargs);
-        Py_DECREF(args);
         PyErr_Format(st->UnpicklingError,
                      "NEWOBJ_EX class argument must be a type, not %.200s",
                      Py_TYPE(cls)->tp_name);
-        Py_DECREF(cls);
-        return -1;
+        goto error;
     }
 
     if (((PyTypeObject *)cls)->tp_new == NULL) {
-        Py_DECREF(kwargs);
-        Py_DECREF(args);
-        Py_DECREF(cls);
         PyErr_SetString(st->UnpicklingError,
                         "NEWOBJ_EX class argument doesn't have __new__");
-        return -1;
+        goto error;
+    }
+    if (!PyTuple_Check(args)) {
+        PyErr_Format(st->UnpicklingError,
+                     "NEWOBJ_EX args argument must be a tuple, not %.200s",
+                     Py_TYPE(args)->tp_name);
+        goto error;
+    }
+    if (!PyDict_Check(kwargs)) {
+        PyErr_Format(st->UnpicklingError,
+                     "NEWOBJ_EX kwargs argument must be a dict, not %.200s",
+                     Py_TYPE(kwargs)->tp_name);
+        goto error;
     }
+
     obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
     Py_DECREF(kwargs);
     Py_DECREF(args);
@@ -6014,6 +6021,12 @@ load_newobj_ex(UnpicklerObject *self)
     }
     PDATA_PUSH(self->stack, obj, -1);
     return 0;
+
+error:
+    Py_DECREF(kwargs);
+    Py_DECREF(args);
+    Py_DECREF(cls);
+    return -1;
 }
 
 static int
index b35f708f95bc2181ec7b01b54aec89dbe7ad76ca..27aac70f06ff01378a9861b0f6114ac90491d448 100644 (file)
@@ -254,7 +254,7 @@ struct PostCallbackData {
 };
 
 static VOID CALLBACK
-PostToQueueCallback(PVOID lpParameter, BOOL TimerOrWaitFired)
+PostToQueueCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
 {
     struct PostCallbackData *p = (struct PostCallbackData*) lpParameter;
 
@@ -295,8 +295,7 @@ overlapped_RegisterWaitWithQueue(PyObject *self, PyObject *args)
     *pdata = data;
 
     if (!RegisterWaitForSingleObject(
-            &NewWaitObject, Object, (WAITORTIMERCALLBACK)PostToQueueCallback,
-            pdata, Milliseconds,
+            &NewWaitObject, Object, PostToQueueCallback, pdata, Milliseconds,
             WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
     {
         PyMem_RawFree(pdata);
index 00128698cd01889fe5a8e784c0cc2b4cdaca7028..0acde714a87b146ea2c0dda0cc614083a96a8f7e 100644 (file)
@@ -5822,14 +5822,29 @@ hackcheck(PyObject *self, setattrofunc func, const char *what)
         return 1;
     }
     assert(PyTuple_Check(mro));
-    Py_ssize_t i, n;
-    n = PyTuple_GET_SIZE(mro);
-    for (i = 0; i < n; i++) {
+
+    /* Find the (base) type that defined the type's slot function. */
+    PyTypeObject *defining_type = type;
+    Py_ssize_t i;
+    for (i = PyTuple_GET_SIZE(mro) - 1; i >= 0; i--) {
         PyTypeObject *base = (PyTypeObject*) PyTuple_GET_ITEM(mro, i);
+        if (base->tp_setattro == slot_tp_setattro) {
+            /* Ignore Python classes:
+               they never define their own C-level setattro. */
+        }
+        else if (base->tp_setattro == type->tp_setattro) {
+            defining_type = base;
+            break;
+        }
+    }
+
+    /* Reject calls that jump over intermediate C-level overrides. */
+    for (PyTypeObject *base = defining_type; base; base = base->tp_base) {
         if (base->tp_setattro == func) {
-            /* 'func' is the earliest non-Python implementation in the MRO. */
+            /* 'func' is the right slot function to call. */
             break;
-        } else if (base->tp_setattro != slot_tp_setattro) {
+        }
+        else if (base->tp_setattro != slot_tp_setattro) {
             /* 'base' is not a Python class and overrides 'func'.
                Its tp_setattro should be called instead. */
             PyErr_Format(PyExc_TypeError,
@@ -5839,8 +5854,6 @@ hackcheck(PyObject *self, setattrofunc func, const char *what)
             return 0;
         }
     }
-    /* Either 'func' is not in the mro (which should fail when checking 'self'),
-       or it's the right slot function to call. */
     return 1;
 }
 
index cf20b9f613c87b7f49eb3d6afbd297d3821247b9..8969fb554ab7cade54e849460050e9c155430310 100644 (file)
@@ -717,7 +717,7 @@ static int
 get_pth_filename(PyCalculatePath *calculate, wchar_t *filename,
                  const _PyPathConfig *pathconfig)
 {
-    if (get_dllpath(filename) &&
+    if (!get_dllpath(filename) &&
         !change_ext(filename, filename, L"._pth") &&
         exists(filename))
     {
index 5678b05ced3698e973c6ae01e3e6eafa295056e7..78b99a77206c9485a04fce70ec205df55a76e702 100644 (file)
@@ -130,7 +130,7 @@ do { \
 static pthread_condattr_t *condattr_monotonic = NULL;
 
 static void
-init_condattr()
+init_condattr(void)
 {
 #ifdef CONDATTR_MONOTONIC
     static pthread_condattr_t ca;
index 51a053025f65fcb6be083e9ad1948bc9fa65d41c..862a24d5efc03ea2dddca506c88e76039dfc1d61 100644 (file)
@@ -1,4 +1,4 @@
-This is Python version 3.8.4
+This is Python version 3.8.5
 ============================
 
 .. image:: https://travis-ci.org/python/cpython.svg?branch=3.8