From: DongHun Kwak Date: Wed, 9 Dec 2020 00:40:18 +0000 (+0900) Subject: Imported Upstream version 3.8.5 X-Git-Tag: upstream/3.8.5^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0022de3c1fc2245da59c3f5a55496f448d429cc8;p=platform%2Fupstream%2Fpython3.git Imported Upstream version 3.8.5 --- diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 00ce5d4b..c96dde2d 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -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*. diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst index 8169bd35..38173f18 100644 --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -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 diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index ec9521f1..bb3ee87a 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -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 diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index e92f5545..34966b38 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -647,6 +647,9 @@ the *new_callable* argument to :func:`patch`. arguments and make more complex assertions. See :ref:`calls as tuples `. + .. versionchanged:: 3.8 + Added ``args`` and ``kwargs`` properties. + .. attribute:: call_args_list diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index 52f98ef3..25e5cc1a 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -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 diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 250d2a9d..685552f9 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -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 diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index d2db5bff..475e3ab9 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -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 diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 41901a58..25fc2d3a 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--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. diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 38d98271..66e81f92 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -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: diff --git a/Lib/http/client.py b/Lib/http/client.py index 019380a7..c2ad0471 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -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. diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index b43c6d3a..ddc1e22e 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -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. diff --git a/Lib/idlelib/iomenu.py b/Lib/idlelib/iomenu.py index 7641d866..74ebefd4 100644 --- a/Lib/idlelib/iomenu.py +++ b/Lib/idlelib/iomenu.py @@ -1,3 +1,4 @@ +import io import os import shlex import sys diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index d4473aaa..68346572 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -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' diff --git a/Lib/tarfile.py b/Lib/tarfile.py index d31b9cbb..7a69e1b1 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -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" diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 9401043d..ff7bbb0c 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -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 index 00000000..b8237251 Binary files /dev/null and b/Lib/test/recursion.tar differ diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index c4d900a8..18397a86 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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 diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 8f0e27a1..5a5fcecb 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -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" diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 9a047fd4..01008656 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -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() diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 15324a4e..b512168d 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -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 diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 4fab4882..a58b922c 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -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 ' diff --git a/Misc/NEWS b/Misc/NEWS index 7486b797..c7c412e3 100644 --- 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? ================================= diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index df7c6e25..eb1f1a01 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -58,6 +58,13 @@ #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 diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 55affb2c..42ce62fc 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -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 diff --git a/Modules/overlapped.c b/Modules/overlapped.c index b35f708f..27aac70f 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -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); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 00128698..0acde714 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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; } diff --git a/PC/getpathp.c b/PC/getpathp.c index cf20b9f6..8969fb55 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -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)) { diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 5678b05c..78b99a77 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -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; diff --git a/README.rst b/README.rst index 51a05302..862a24d5 100644 --- a/README.rst +++ b/README.rst @@ -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