From: DongHun Kwak Date: Mon, 16 Oct 2017 10:56:56 +0000 (+0900) Subject: Imported Upstream version 3.4.6 X-Git-Tag: upstream/3.6.3~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F96%2F155896%2F1;p=platform%2Fupstream%2Fpython3.git Imported Upstream version 3.4.6 Change-Id: Ie4ae6130d0009ab511f9747ebba92ae519e8752b Signed-off-by: DongHun Kwak --- diff --git a/Doc/Makefile b/Doc/Makefile index ea30231..e3d204d 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -95,8 +95,8 @@ doctest: pydoc-topics: BUILDER = pydoc-topics pydoc-topics: build - @echo "Building finished; now copy build/pydoc-topics/topics.py" \ - "to ../Lib/pydoc_data/topics.py" + @echo "Building finished; now run this:" \ + "cp build/pydoc-topics/topics.py ../Lib/pydoc_data/topics.py" htmlview: html $(PYTHON) -c "import webbrowser; webbrowser.open('build/html/index.html')" @@ -161,7 +161,7 @@ autobuild-dev: -make suspicious # for quick rebuilds (HTML only) -autobuild-html: +autobuild-dev-html: make html SPHINXOPTS='-A daily=1 -A versionswitcher=1' # for stable releases: only build if not in pre-release stage (alpha, beta) @@ -173,3 +173,9 @@ autobuild-stable: esac @make autobuild-dev +autobuild-stable-html: + @case $(DISTVERSION) in *[ab]*) \ + echo "Not building; $(DISTVERSION) is not a release version."; \ + exit 1;; \ + esac + @make autobuild-dev-html diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index 9052ed5..540b980 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -538,6 +538,11 @@ setting up a `Basic Authentication`_ handler: :: through a proxy. However, this can be enabled by extending urllib.request as shown in the recipe [#]_. +.. note:: + + ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; see + the documentation on :func:`~urllib.request.getproxies`. + Sockets and Layers ================== diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 4e595de..44db3e1 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -166,6 +166,14 @@ The :mod:`urllib.request` module defines the following functions: cannot find it, looks for proxy information from Mac OSX System Configuration for Mac OS X and Windows Systems Registry for Windows. + .. note:: + + If the environment variable ``REQUEST_METHOD`` is set, which usually + indicates your script is running in a CGI environment, the environment + variable ``HTTP_PROXY`` (uppercase ``_PROXY``) will be ignored. This is + because that variable can be injected by a client using the "Proxy:" HTTP + header. If you need to use an HTTP proxy in a CGI environment use + ``ProxyHandler`` explicitly. The following classes are provided: @@ -268,6 +276,11 @@ The following classes are provided: To disable autodetected proxy pass an empty dictionary. + .. note:: + + ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; + see the documentation on :func:`~urllib.request.getproxies`. + .. class:: HTTPPasswordMgr() diff --git a/Doc/license.rst b/Doc/license.rst index 8a613b2..acbc116 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -84,7 +84,7 @@ Terms and conditions for accessing or otherwise using Python analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python |release| alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of - copyright, i.e., "Copyright © 2001-2016 Python Software Foundation; All Rights + copyright, i.e., "Copyright © 2001-2017 Python Software Foundation; All Rights Reserved" are retained in Python |release| alone or in any derivative version prepared by Licensee. diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 52dfb03..f52922d 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 4 -#define PY_MICRO_VERSION 5 +#define PY_MICRO_VERSION 6 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.4.5" +#define PY_VERSION "3.4.6" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/LICENSE b/LICENSE index 84a3337..f5d0b39 100644 --- a/LICENSE +++ b/LICENSE @@ -74,7 +74,7 @@ analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016 Python Software Foundation; All Rights +2011, 2012, 2013, 2014, 2015, 2016, 2017 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. diff --git a/Lib/ctypes/test/test_callbacks.py b/Lib/ctypes/test/test_callbacks.py index 3824f7c..8eac58f 100644 --- a/Lib/ctypes/test/test_callbacks.py +++ b/Lib/ctypes/test/test_callbacks.py @@ -1,3 +1,4 @@ +import functools import unittest from ctypes import * from ctypes.test import need_symbol @@ -240,6 +241,40 @@ class SampleCallbacksTestCase(unittest.TestCase): self.assertEqual(result, callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5)) + def test_callback_large_struct(self): + class Check: pass + + class X(Structure): + _fields_ = [ + ('first', c_ulong), + ('second', c_ulong), + ('third', c_ulong), + ] + + def callback(check, s): + check.first = s.first + check.second = s.second + check.third = s.third + + check = Check() + s = X() + s.first = 0xdeadbeef + s.second = 0xcafebabe + s.third = 0x0bad1dea + + CALLBACK = CFUNCTYPE(None, X) + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_cbk_large_struct + func.argtypes = (X, CALLBACK) + func.restype = None + # the function just calls the callback with the passed structure + func(s, CALLBACK(functools.partial(callback, check))) + self.assertEqual(check.first, s.first) + self.assertEqual(check.second, s.second) + self.assertEqual(check.third, s.third) + self.assertEqual(check.first, 0xdeadbeef) + self.assertEqual(check.second, 0xcafebabe) + self.assertEqual(check.third, 0x0bad1dea) ################################################################ diff --git a/Lib/distutils/config.py b/Lib/distutils/config.py index 382aca8..64c9b67 100644 --- a/Lib/distutils/config.py +++ b/Lib/distutils/config.py @@ -21,7 +21,7 @@ password:%s class PyPIRCCommand(Command): """Base command that knows how to handle the .pypirc file """ - DEFAULT_REPOSITORY = 'https://pypi.python.org/pypi' + DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/' DEFAULT_REALM = 'pypi' repository = None realm = None diff --git a/Lib/distutils/tests/test_config.py b/Lib/distutils/tests/test_config.py index 4de825a..8286e1d 100644 --- a/Lib/distutils/tests/test_config.py +++ b/Lib/distutils/tests/test_config.py @@ -87,7 +87,7 @@ class PyPIRCCommandTestCase(support.TempdirManager, config = list(sorted(config.items())) waited = [('password', 'secret'), ('realm', 'pypi'), - ('repository', 'https://pypi.python.org/pypi'), + ('repository', 'https://upload.pypi.org/legacy/'), ('server', 'server1'), ('username', 'me')] self.assertEqual(config, waited) @@ -96,7 +96,7 @@ class PyPIRCCommandTestCase(support.TempdirManager, config = cmd._read_pypirc() config = list(sorted(config.items())) waited = [('password', 'secret'), ('realm', 'pypi'), - ('repository', 'https://pypi.python.org/pypi'), + ('repository', 'https://upload.pypi.org/legacy/'), ('server', 'server-login'), ('username', 'tarek')] self.assertEqual(config, waited) diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py index dccaf77..cbbbe33 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py @@ -90,7 +90,7 @@ class uploadTestCase(PyPIRCCommandTestCase): cmd.finalize_options() for attr, waited in (('username', 'me'), ('password', 'secret'), ('realm', 'pypi'), - ('repository', 'https://pypi.python.org/pypi')): + ('repository', 'https://upload.pypi.org/legacy/')): self.assertEqual(getattr(cmd, attr), waited) def test_saved_password(self): @@ -131,7 +131,7 @@ class uploadTestCase(PyPIRCCommandTestCase): content_type = headers['Content-type'] self.assertTrue(content_type.startswith('multipart/form-data')) self.assertEqual(self.last_open.req.get_method(), 'POST') - expected_url = 'https://pypi.python.org/pypi' + expected_url = 'https://upload.pypi.org/legacy/' self.assertEqual(self.last_open.req.get_full_url(), expected_url) self.assertTrue(b'xxx' in self.last_open.req.data) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 08aedf9..25c5567 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ import tempfile __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "20.10.1" +_SETUPTOOLS_VERSION = "28.8.0" -_PIP_VERSION = "8.1.1" +_PIP_VERSION = "9.0.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-8.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-8.1.1-py2.py3-none-any.whl deleted file mode 100644 index 8632eb7..0000000 Binary files a/Lib/ensurepip/_bundled/pip-8.1.1-py2.py3-none-any.whl and /dev/null differ diff --git a/Lib/ensurepip/_bundled/pip-9.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-9.0.1-py2.py3-none-any.whl new file mode 100644 index 0000000..4b8ecc6 Binary files /dev/null and b/Lib/ensurepip/_bundled/pip-9.0.1-py2.py3-none-any.whl differ diff --git a/Lib/ensurepip/_bundled/setuptools-20.10.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-28.8.0-py2.py3-none-any.whl similarity index 51% rename from Lib/ensurepip/_bundled/setuptools-20.10.1-py2.py3-none-any.whl rename to Lib/ensurepip/_bundled/setuptools-28.8.0-py2.py3-none-any.whl index 9d1319a..502e3cb 100644 Binary files a/Lib/ensurepip/_bundled/setuptools-20.10.1-py2.py3-none-any.whl and b/Lib/ensurepip/_bundled/setuptools-28.8.0-py2.py3-none-any.whl differ diff --git a/Lib/gettext.py b/Lib/gettext.py index 8caf1d1..4e6e15e 100644 --- a/Lib/gettext.py +++ b/Lib/gettext.py @@ -59,55 +59,147 @@ __all__ = ['NullTranslations', 'GNUTranslations', 'Catalog', _default_localedir = os.path.join(sys.base_prefix, 'share', 'locale') +# Expression parsing for plural form selection. +# +# The gettext library supports a small subset of C syntax. The only +# incompatible difference is that integer literals starting with zero are +# decimal. +# +# https://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms +# http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/plural.y + +_token_pattern = re.compile(r""" + (?P[ \t]+) | # spaces and horizontal tabs + (?P[0-9]+\b) | # decimal integer + (?Pn\b) | # only n is allowed + (?P[()]) | + (?P[-*/%+?:]|[>, + # <=, >=, ==, !=, &&, ||, + # ? : + # unary and bitwise ops + # not allowed + (?P\w+|.) # invalid token + """, re.VERBOSE|re.DOTALL) + +def _tokenize(plural): + for mo in re.finditer(_token_pattern, plural): + kind = mo.lastgroup + if kind == 'WHITESPACES': + continue + value = mo.group(kind) + if kind == 'INVALID': + raise ValueError('invalid token in plural form: %s' % value) + yield value + yield '' + +def _error(value): + if value: + return ValueError('unexpected token in plural form: %s' % value) + else: + return ValueError('unexpected end of plural form') + +_binary_ops = ( + ('||',), + ('&&',), + ('==', '!='), + ('<', '>', '<=', '>='), + ('+', '-'), + ('*', '/', '%'), +) +_binary_ops = {op: i for i, ops in enumerate(_binary_ops, 1) for op in ops} +_c2py_ops = {'||': 'or', '&&': 'and', '/': '//'} + +def _parse(tokens, priority=-1): + result = '' + nexttok = next(tokens) + while nexttok == '!': + result += 'not ' + nexttok = next(tokens) + + if nexttok == '(': + sub, nexttok = _parse(tokens) + result = '%s(%s)' % (result, sub) + if nexttok != ')': + raise ValueError('unbalanced parenthesis in plural form') + elif nexttok == 'n': + result = '%s%s' % (result, nexttok) + else: + try: + value = int(nexttok, 10) + except ValueError: + raise _error(nexttok) from None + result = '%s%d' % (result, value) + nexttok = next(tokens) + + j = 100 + while nexttok in _binary_ops: + i = _binary_ops[nexttok] + if i < priority: + break + # Break chained comparisons + if i in (3, 4) and j in (3, 4): # '==', '!=', '<', '>', '<=', '>=' + result = '(%s)' % result + # Replace some C operators by their Python equivalents + op = _c2py_ops.get(nexttok, nexttok) + right, nexttok = _parse(tokens, i + 1) + result = '%s %s %s' % (result, op, right) + j = i + if j == priority == 4: # '<', '>', '<=', '>=' + result = '(%s)' % result + + if nexttok == '?' and priority <= 0: + if_true, nexttok = _parse(tokens, 0) + if nexttok != ':': + raise _error(nexttok) + if_false, nexttok = _parse(tokens) + result = '%s if %s else %s' % (if_true, result, if_false) + if priority == 0: + result = '(%s)' % result + + return result, nexttok + +def _as_int(n): + try: + i = round(n) + except TypeError: + raise TypeError('Plural value must be an integer, got %s' % + (n.__class__.__name__,)) from None + return n def c2py(plural): """Gets a C expression as used in PO files for plural forms and returns a - Python lambda function that implements an equivalent expression. + Python function that implements an equivalent expression. """ - # Security check, allow only the "n" identifier - import token, tokenize - tokens = tokenize.generate_tokens(io.StringIO(plural).readline) - try: - danger = [x for x in tokens if x[0] == token.NAME and x[1] != 'n'] - except tokenize.TokenError: - raise ValueError('plural forms expression error, maybe unbalanced parenthesis') - else: - if danger: - raise ValueError('plural forms expression could be dangerous') - - # Replace some C operators by their Python equivalents - plural = plural.replace('&&', ' and ') - plural = plural.replace('||', ' or ') - - expr = re.compile(r'\!([^=])') - plural = expr.sub(' not \\1', plural) - - # Regular expression and replacement function used to transform - # "a?b:c" to "b if a else c". - expr = re.compile(r'(.*?)\?(.*?):(.*)') - def repl(x): - return "(%s if %s else %s)" % (x.group(2), x.group(1), - expr.sub(repl, x.group(3))) - - # Code to transform the plural expression, taking care of parentheses - stack = [''] - for c in plural: - if c == '(': - stack.append('') - elif c == ')': - if len(stack) == 1: - # Actually, we never reach this code, because unbalanced - # parentheses get caught in the security check at the - # beginning. - raise ValueError('unbalanced parenthesis in plural form') - s = expr.sub(repl, stack.pop()) - stack[-1] += '(%s)' % s - else: - stack[-1] += c - plural = expr.sub(repl, stack.pop()) - - return eval('lambda n: int(%s)' % plural) + if len(plural) > 1000: + raise ValueError('plural form expression is too long') + try: + result, nexttok = _parse(_tokenize(plural)) + if nexttok: + raise _error(nexttok) + + depth = 0 + for c in result: + if c == '(': + depth += 1 + if depth > 20: + # Python compiler limit is about 90. + # The most complex example has 2. + raise ValueError('plural form expression is too complex') + elif c == ')': + depth -= 1 + + ns = {'_as_int': _as_int} + exec('''if True: + def func(n): + if not isinstance(n, int): + n = _as_int(n) + return int(%s) + ''' % result, ns) + return ns['func'] + except RuntimeError: + # Recursion error can be raised in _parse() or exec(). + raise ValueError('plural form expression is too complex') def _expand_lang(loc): diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 0c43c25..1cc4ef5 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sat Jun 25 14:40:57 2016 +# Autogenerated by Sphinx on Sun Jan 1 22:08:13 2017 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', diff --git a/Lib/selectors.py b/Lib/selectors.py index 7b6da29..8936ab6 100644 --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -399,7 +399,11 @@ if hasattr(select, 'epoll'): epoll_events |= select.EPOLLIN if events & EVENT_WRITE: epoll_events |= select.EPOLLOUT - self._epoll.register(key.fd, epoll_events) + try: + self._epoll.register(key.fd, epoll_events) + except BaseException: + super().unregister(fileobj) + raise return key def unregister(self, fileobj): @@ -465,14 +469,18 @@ if hasattr(select, 'kqueue'): def register(self, fileobj, events, data=None): key = super().register(fileobj, events, data) - if events & EVENT_READ: - kev = select.kevent(key.fd, select.KQ_FILTER_READ, - select.KQ_EV_ADD) - self._kqueue.control([kev], 0, 0) - if events & EVENT_WRITE: - kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, - select.KQ_EV_ADD) - self._kqueue.control([kev], 0, 0) + try: + if events & EVENT_READ: + kev = select.kevent(key.fd, select.KQ_FILTER_READ, + select.KQ_EV_ADD) + self._kqueue.control([kev], 0, 0) + if events & EVENT_WRITE: + kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, + select.KQ_EV_ADD) + self._kqueue.control([kev], 0, 0) + except BaseException: + super().unregister(fileobj) + raise return key def unregister(self, fileobj): diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index bd7d4fc..379721a 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -163,6 +163,11 @@ class TestCurses(unittest.TestCase): if hasattr(curses, 'enclose'): stdscr.enclose() + self.assertRaises(ValueError, stdscr.getstr, -400) + self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400) + self.assertRaises(ValueError, stdscr.instr, -2) + self.assertRaises(ValueError, stdscr.instr, 2, 3, -2) + def test_module_funcs(self): "Test module-level functions" diff --git a/Lib/test/test_gettext.py b/Lib/test/test_gettext.py index 2737e81..80b18da 100644 --- a/Lib/test/test_gettext.py +++ b/Lib/test/test_gettext.py @@ -236,7 +236,9 @@ class PluralFormsTestCase(GettextBaseTest): x = t.ngettext('There is %s file', 'There are %s files', 2) eq(x, 'Hay %s ficheros') - def test_hu(self): + # Examples from http://www.gnu.org/software/gettext/manual/gettext.html + + def test_ja(self): eq = self.assertEqual f = gettext.c2py('0') s = ''.join([ str(f(x)) for x in range(200) ]) @@ -254,6 +256,12 @@ class PluralFormsTestCase(GettextBaseTest): s = ''.join([ str(f(x)) for x in range(200) ]) eq(s, "00111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") + def test_lv(self): + eq = self.assertEqual + f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2') + s = ''.join([ str(f(x)) for x in range(200) ]) + eq(s, "20111111111111111111101111111110111111111011111111101111111110111111111011111111101111111110111111111011111111111111111110111111111011111111101111111110111111111011111111101111111110111111111011111111") + def test_gd(self): eq = self.assertEqual f = gettext.c2py('n==1 ? 0 : n==2 ? 1 : 2') @@ -267,6 +275,12 @@ class PluralFormsTestCase(GettextBaseTest): s = ''.join([ str(f(x)) for x in range(200) ]) eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") + def test_ro(self): + eq = self.assertEqual + f = gettext.c2py('n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2') + s = ''.join([ str(f(x)) for x in range(200) ]) + eq(s, "10111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222") + def test_lt(self): eq = self.assertEqual f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2') @@ -279,6 +293,12 @@ class PluralFormsTestCase(GettextBaseTest): s = ''.join([ str(f(x)) for x in range(200) ]) eq(s, "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222") + def test_cs(self): + eq = self.assertEqual + f = gettext.c2py('(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2') + s = ''.join([ str(f(x)) for x in range(200) ]) + eq(s, "20111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") + def test_pl(self): eq = self.assertEqual f = gettext.c2py('n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2') @@ -291,10 +311,77 @@ class PluralFormsTestCase(GettextBaseTest): s = ''.join([ str(f(x)) for x in range(200) ]) eq(s, "30122333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333012233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333") + def test_ar(self): + eq = self.assertEqual + f = gettext.c2py('n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5') + s = ''.join([ str(f(x)) for x in range(200) ]) + eq(s, "01233333333444444444444444444444444444444444444444444444444444444444444444444444444444444444444444445553333333344444444444444444444444444444444444444444444444444444444444444444444444444444444444444444") + def test_security(self): raises = self.assertRaises # Test for a dangerous expression raises(ValueError, gettext.c2py, "os.chmod('/etc/passwd',0777)") + # issue28563 + raises(ValueError, gettext.c2py, '"(eval(foo) && ""') + raises(ValueError, gettext.c2py, 'f"{os.system(\'sh\')}"') + # Maximum recursion depth exceeded during compilation + raises(ValueError, gettext.c2py, 'n+'*10000 + 'n') + self.assertEqual(gettext.c2py('n+'*100 + 'n')(1), 101) + # MemoryError during compilation + raises(ValueError, gettext.c2py, '('*100 + 'n' + ')'*100) + # Maximum recursion depth exceeded in C to Python translator + raises(ValueError, gettext.c2py, '('*10000 + 'n' + ')'*10000) + self.assertEqual(gettext.c2py('('*20 + 'n' + ')'*20)(1), 1) + + def test_chained_comparison(self): + # C doesn't chain comparison as Python so 2 == 2 == 2 gets different results + f = gettext.c2py('n == n == n') + self.assertEqual(''.join(str(f(x)) for x in range(3)), '010') + f = gettext.c2py('1 < n == n') + self.assertEqual(''.join(str(f(x)) for x in range(3)), '100') + f = gettext.c2py('n == n < 2') + self.assertEqual(''.join(str(f(x)) for x in range(3)), '010') + f = gettext.c2py('0 < n < 2') + self.assertEqual(''.join(str(f(x)) for x in range(3)), '111') + + def test_decimal_number(self): + self.assertEqual(gettext.c2py('0123')(1), 123) + + def test_invalid_syntax(self): + invalid_expressions = [ + 'x>1', '(n>1', 'n>1)', '42**42**42', '0xa', '1.0', '1e2', + 'n>0x1', '+n', '-n', 'n()', 'n(1)', '1+', 'nn', 'n n', + ] + for expr in invalid_expressions: + with self.assertRaises(ValueError): + gettext.c2py(expr) + + def test_nested_condition_operator(self): + self.assertEqual(gettext.c2py('n?1?2:3:4')(0), 4) + self.assertEqual(gettext.c2py('n?1?2:3:4')(1), 2) + self.assertEqual(gettext.c2py('n?1:3?4:5')(0), 4) + self.assertEqual(gettext.c2py('n?1:3?4:5')(1), 1) + + def test_division(self): + f = gettext.c2py('2/n*3') + self.assertEqual(f(1), 6) + self.assertEqual(f(2), 3) + self.assertEqual(f(3), 0) + self.assertEqual(f(-1), -6) + self.assertRaises(ZeroDivisionError, f, 0) + + def test_plural_number(self): + f = gettext.c2py('n != 1') + self.assertEqual(f(1), 0) + self.assertEqual(f(2), 1) + self.assertEqual(f(1.0), 0) + self.assertEqual(f(2.0), 1) + self.assertEqual(f(1.1), 1) + self.assertRaises(TypeError, f, '2') + self.assertRaises(TypeError, f, b'2') + self.assertRaises(TypeError, f, []) + self.assertRaises(TypeError, f, object()) + class GNUTranslationParsingTest(GettextBaseTest): def test_plural_form_error_issue17898(self): diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 216a46b..8ec808b 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -662,11 +662,9 @@ class MalformedInputTest(unittest.TestCase): # \xc2\x85 is UTF-8 encoded U+0085 (NEXT LINE) xml = b"\r\n" parser = expat.ParserCreate() - try: + err_pattern = r'XML declaration not well-formed: line 1, column \d+' + with self.assertRaisesRegex(expat.ExpatError, err_pattern): parser.Parse(xml, True) - self.fail() - except expat.ExpatError as e: - self.assertEqual(str(e), 'XML declaration not well-formed: line 1, column 14') class ErrorMessageTest(unittest.TestCase): def test_codes(self): diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 952fda6..28cd948 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -5,6 +5,7 @@ import selectors import signal import socket import sys +import tempfile from test import support from time import sleep import unittest @@ -447,6 +448,16 @@ class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): SELECTOR = getattr(selectors, 'EpollSelector', None) + def test_register_file(self): + # epoll(7) returns EPERM when given a file to watch + s = self.SELECTOR() + with tempfile.NamedTemporaryFile() as f: + with self.assertRaises(IOError): + s.register(f, selectors.EVENT_READ) + # the SelectorKey has been removed + with self.assertRaises(KeyError): + s.get_key(f) + @unittest.skipUnless(hasattr(selectors, 'KqueueSelector'), "Test needs selectors.KqueueSelector)") @@ -454,6 +465,18 @@ class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): SELECTOR = getattr(selectors, 'KqueueSelector', None) + def test_register_bad_fd(self): + # a file descriptor that's been closed should raise an OSError + # with EBADF + s = self.SELECTOR() + bad_f = support.make_bad_fd() + with self.assertRaises(OSError) as cm: + s.register(bad_f, selectors.EVENT_READ) + self.assertEqual(cm.exception.errno, errno.EBADF) + # the SelectorKey has been removed + with self.assertRaises(KeyError): + s.get_key(bad_f) + def test_main(): tests = [DefaultSelectorTestCase, SelectSelectorTestCase, diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index e100039..87171e9 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -222,6 +222,19 @@ class ProxyTests(unittest.TestCase): self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com') self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com')) + def test_proxy_cgi_ignore(self): + try: + self.env.set('HTTP_PROXY', 'http://somewhere:3128') + proxies = urllib.request.getproxies_environment() + self.assertEqual('http://somewhere:3128', proxies['http']) + self.env.set('REQUEST_METHOD', 'GET') + proxies = urllib.request.getproxies_environment() + self.assertNotIn('http', proxies) + finally: + self.env.unset('REQUEST_METHOD') + self.env.unset('HTTP_PROXY') + + class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin, FakeFTPMixin): """Test urlopen() opening a fake http connection.""" diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py index 42ebb6e..5331afc 100644 --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -89,7 +89,7 @@ class urlopenNetworkTests(unittest.TestCase): def test_getcode(self): # test getcode() with the fancy opener to get 404 error codes - URL = "http://www.example.com/XXXinvalidXXX" + URL = "http://www.pythontest.net/XXXinvalidXXX" with support.transient_internet(URL): with self.assertWarns(DeprecationWarning): open_url = urllib.request.FancyURLopener().open(URL) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 376bba4..f769386 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -2337,6 +2337,13 @@ def getproxies_environment(): name = name.lower() if value and name[-6:] == '_proxy': proxies[name[:-6]] = value + + # CVE-2016-1000110 - If we are running as CGI script, forget HTTP_PROXY + # (non-all-lowercase) as it may be set from the web server by a "Proxy:" + # header from the client + if 'REQUEST_METHOD' in os.environ: + proxies.pop('http', None) + return proxies def proxy_bypass_environment(host): diff --git a/Mac/IDLE/IDLE.app/Contents/Info.plist b/Mac/IDLE/IDLE.app/Contents/Info.plist index f7c3b35..5507687 100644 --- a/Mac/IDLE/IDLE.app/Contents/Info.plist +++ b/Mac/IDLE/IDLE.app/Contents/Info.plist @@ -36,7 +36,7 @@ CFBundleExecutable IDLE CFBundleGetInfoString - %version%, © 2001-2016 Python Software Foundation + %version%, © 2001-2017 Python Software Foundation CFBundleIconFile IDLE.icns CFBundleIdentifier diff --git a/Mac/PythonLauncher/Info.plist.in b/Mac/PythonLauncher/Info.plist.in index 6c4bfe8..1a8e2b4 100644 --- a/Mac/PythonLauncher/Info.plist.in +++ b/Mac/PythonLauncher/Info.plist.in @@ -40,7 +40,7 @@ CFBundleExecutable PythonLauncher CFBundleGetInfoString - %VERSION%, © 2001-2016 Python Software Foundation + %VERSION%, © 2001-2017 Python Software Foundation CFBundleIconFile PythonLauncher.icns CFBundleIdentifier diff --git a/Mac/Resources/app/Info.plist.in b/Mac/Resources/app/Info.plist.in index a0bb971..a23166e 100644 --- a/Mac/Resources/app/Info.plist.in +++ b/Mac/Resources/app/Info.plist.in @@ -37,7 +37,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - %version%, (c) 2001-2016 Python Software Foundation. + %version%, (c) 2001-2017 Python Software Foundation. CFBundleName Python CFBundlePackageType diff --git a/Mac/Resources/framework/Info.plist.in b/Mac/Resources/framework/Info.plist.in index fcba7d9..7a64619 100644 --- a/Mac/Resources/framework/Info.plist.in +++ b/Mac/Resources/framework/Info.plist.in @@ -17,9 +17,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - %VERSION%, (c) 2001-2016 Python Software Foundation. + %VERSION%, (c) 2001-2017 Python Software Foundation. CFBundleLongVersionString - %VERSION%, (c) 2001-2016 Python Software Foundation. + %VERSION%, (c) 2001-2017 Python Software Foundation. CFBundleSignature ???? CFBundleVersion diff --git a/Misc/NEWS b/Misc/NEWS index b0a8573..c3dc15e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,66 @@ Python News +++++++++++ +What's New in Python 3.4.6? +=========================== + +Release date: 2017-01-16 + +There were no changes between 3.4.6rc1 and 3.4.6 final. + + +What's New in Python 3.4.6rc1? +============================== + +Release date: 2017-01-02 + +Core and Builtins +----------------- + +- Issue #28648: Fixed crash in Py_DecodeLocale() in debug build on Mac OS X + when decode astral characters. Patch by Xiang Zhang. + +- Issue #28426: Fixed potential crash in PyUnicode_AsDecodedObject() in debug + build. + +Library +------- + +- Issue #28563: Fixed possible DoS and arbitrary code execution when handle + plural form selections in the gettext module. The expression parser now + supports exact syntax supported by GNU gettext. + +- In the curses module, raise an error if window.getstr() or window.instr() is + passed a negative value. + +- Issue #27783: Fix possible usage of uninitialized memory in operator.methodcaller. + +- Issue #27774: Fix possible Py_DECREF on unowned object in _sre. + +- Issue #27760: Fix possible integer overflow in binascii.b2a_qp. + +- Issue #27758: Fix possible integer overflow in the _csv module for large record + lengths. + +- Issue #27568: Prevent HTTPoxy attack (CVE-2016-1000110). Ignore the + HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates + that the script is in CGI mode. + +- Issue #27759: Fix selectors incorrectly retain invalid file descriptors. + Patch by Mark Williams. + +Build +----- + +- Issue #28248: Update Windows build to use OpenSSL 1.0.2j. + +Tests +----- + +- Issue #27369: In test_pyexpat, avoid testing an error message detail that + changed in Expat 2.2.0. + + What's New in Python 3.4.5? =========================== diff --git a/Modules/_csv.c b/Modules/_csv.c index 1a363fa..ed6055d 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -1016,11 +1016,19 @@ join_append_data(WriterObj *self, unsigned int field_kind, void *field_data, int i; Py_ssize_t rec_len; -#define ADDCH(c) \ +#define INCLEN \ + do {\ + if (!copy_phase && rec_len == PY_SSIZE_T_MAX) { \ + goto overflow; \ + } \ + rec_len++; \ + } while(0) + +#define ADDCH(c) \ do {\ if (copy_phase) \ self->rec[rec_len] = c;\ - rec_len++;\ + INCLEN;\ } while(0) rec_len = self->rec_len; @@ -1086,11 +1094,18 @@ join_append_data(WriterObj *self, unsigned int field_kind, void *field_data, if (*quoted) { if (copy_phase) ADDCH(dialect->quotechar); - else - rec_len += 2; + else { + INCLEN; /* starting quote */ + INCLEN; /* ending quote */ + } } return rec_len; + + overflow: + PyErr_NoMemory(); + return -1; #undef ADDCH +#undef INCLEN } static int diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index f957e02..3c7f892 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -26,6 +26,24 @@ _testfunc_cbk_reg_double(double a, double b, double c, double d, double e, return func(a*a, b*b, c*c, d*d, e*e); } +/* + * This structure should be the same as in test_callbacks.py and the + * method test_callback_large_struct. See issues 17310 and 20160: the + * structure must be larger than 8 bytes long. + */ + +typedef struct { + unsigned long first; + unsigned long second; + unsigned long third; +} Test; + +EXPORT(void) +_testfunc_cbk_large_struct(Test in, void (*func)(Test)) +{ + func(in); +} + EXPORT(void)testfunc_array(int values[4]) { printf("testfunc_array %d %d %d %d\n", diff --git a/Modules/_ctypes/libffi_msvc/ffi.c b/Modules/_ctypes/libffi_msvc/ffi.c index 76cb03e..966e05c 100644 --- a/Modules/_ctypes/libffi_msvc/ffi.c +++ b/Modules/_ctypes/libffi_msvc/ffi.c @@ -359,7 +359,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, if ( cif->rtype->type == FFI_TYPE_STRUCT ) { *rvalue = *(void **) argp; - argp += 4; + argp += sizeof(void *); } p_argv = avalue; @@ -370,13 +370,23 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, /* Align if necessary */ if ((sizeof(char *) - 1) & (size_t) argp) { - argp = (char *) ALIGN(argp, sizeof(char*)); + argp = (char *) ALIGN(argp, sizeof(char*)); } z = (*p_arg)->size; /* because we're little endian, this is what it turns into. */ +#ifdef _WIN64 + if (z > 8) { + /* On Win64, if a single argument takes more than 8 bytes, + * then it is always passed by reference. + */ + *p_argv = *((void**) argp); + z = 8; + } + else +#endif *p_argv = (void*) argp; p_argv++; diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5ffce2f..501ec91 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1284,6 +1284,10 @@ PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args) case 1: if (!PyArg_ParseTuple(args,"i;n", &n)) return NULL; + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); + return NULL; + } Py_BEGIN_ALLOW_THREADS rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023)); Py_END_ALLOW_THREADS @@ -1302,6 +1306,10 @@ PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args) case 3: if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n)) return NULL; + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); + return NULL; + } #ifdef STRICT_SYSV_CURSES Py_BEGIN_ALLOW_THREADS rtn2 = wmove(self->win,y,x)==ERR ? ERR : @@ -1448,6 +1456,10 @@ PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args) case 1: if (!PyArg_ParseTuple(args,"i;n", &n)) return NULL; + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); + return NULL; + } rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023)); break; case 2: @@ -1458,6 +1470,10 @@ PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args) case 3: if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n)) return NULL; + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); + return NULL; + } rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023)); break; default: diff --git a/Modules/_operator.c b/Modules/_operator.c index adeb99e..f294769 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -801,7 +801,7 @@ static PyObject * methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { methodcallerobject *mc; - PyObject *name, *newargs; + PyObject *name; if (PyTuple_GET_SIZE(args) < 1) { PyErr_SetString(PyExc_TypeError, "methodcaller needs at least " @@ -814,13 +814,6 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (mc == NULL) return NULL; - newargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); - if (newargs == NULL) { - Py_DECREF(mc); - return NULL; - } - mc->args = newargs; - name = PyTuple_GET_ITEM(args, 0); Py_INCREF(name); mc->name = name; @@ -828,6 +821,12 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_XINCREF(kwds); mc->kwds = kwds; + mc->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); + if (mc->args == NULL) { + Py_DECREF(mc); + return NULL; + } + PyObject_GC_Track(mc); return (PyObject *)mc; } diff --git a/Modules/_sre.c b/Modules/_sre.c index d6fcda1..8d111e3 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -2137,10 +2137,8 @@ match_groupdict(MatchObject* self, PyObject* args, PyObject* kw) if (!key) goto failed; value = match_getslice(self, key, def); - if (!value) { - Py_DECREF(key); + if (!value) goto failed; - } status = PyDict_SetItem(result, key, value); Py_DECREF(value); if (status < 0) diff --git a/Modules/binascii.c b/Modules/binascii.c index ea14d3c..c9309ce 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -1408,6 +1408,7 @@ binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, int is /* First, scan to see how many characters need to be encoded */ in = 0; while (in < datalen) { + Py_ssize_t delta = 0; if ((databuf[in] > 126) || (databuf[in] == '=') || (header && databuf[in] == '_') || @@ -1422,12 +1423,12 @@ binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, int is if ((linelen + 3) >= MAXLINESIZE) { linelen = 0; if (crlf) - odatalen += 3; + delta += 3; else - odatalen += 2; + delta += 2; } linelen += 3; - odatalen += 3; + delta += 3; in++; } else { @@ -1439,11 +1440,11 @@ binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, int is linelen = 0; /* Protect against whitespace on end of line */ if (in && ((databuf[in-1] == ' ') || (databuf[in-1] == '\t'))) - odatalen += 2; + delta += 2; if (crlf) - odatalen += 2; + delta += 2; else - odatalen += 1; + delta += 1; if (databuf[in] == '\r') in += 2; else @@ -1455,15 +1456,20 @@ binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, int is (linelen + 1) >= MAXLINESIZE) { linelen = 0; if (crlf) - odatalen += 3; + delta += 3; else - odatalen += 2; + delta += 2; } linelen++; - odatalen++; + delta++; in++; } } + if (PY_SSIZE_T_MAX - delta < odatalen) { + PyErr_NoMemory(); + return NULL; + } + odatalen += delta; } /* We allocate the output same size as input, this is overkill. diff --git a/Modules/expat/xmlrole.c b/Modules/expat/xmlrole.c index 9a8f85d..44772e2 100644 --- a/Modules/expat/xmlrole.c +++ b/Modules/expat/xmlrole.c @@ -2,6 +2,8 @@ See the file COPYING for copying permission. */ +#include + #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) @@ -16,8 +18,6 @@ #endif #endif /* ndef COMPILED_FROM_DSP */ -#include - #include "expat_external.h" #include "internal.h" #include "xmlrole.h" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c index 205c07e..bf09dfc 100644 --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -2,6 +2,8 @@ See the file COPYING for copying permission. */ +#include + #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) @@ -16,8 +18,6 @@ #endif #endif /* ndef COMPILED_FROM_DSP */ -#include - #include "expat_external.h" #include "internal.h" #include "xmltok.h" diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 193d898..ee6eac3 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3059,24 +3059,16 @@ PyUnicode_AsDecodedObject(PyObject *unicode, const char *encoding, const char *errors) { - PyObject *v; - if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); - goto onError; + return NULL; } if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Decode via the codec registry */ - v = PyCodec_Decode(unicode, encoding, errors); - if (v == NULL) - goto onError; - return unicode_result(v); - - onError: - return NULL; + return PyCodec_Decode(unicode, encoding, errors); } PyObject * @@ -4864,7 +4856,7 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size) #if SIZEOF_WCHAR_T == 4 assert(0); #else - assert(Py_UNICODE_IS_SURROGATE(ch)); + assert(ch > 0xFFFF && ch <= MAX_UNICODE); /* compute and append the two surrogates: */ unicode[outpos++] = (wchar_t)Py_UNICODE_HIGH_SURROGATE(ch); unicode[outpos++] = (wchar_t)Py_UNICODE_LOW_SURROGATE(ch); diff --git a/PC/python_nt.rc b/PC/python_nt.rc index 0fbdbe0..51b9798 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -61,7 +61,7 @@ BEGIN VALUE "FileDescription", "Python Core\0" VALUE "FileVersion", PYTHON_VERSION VALUE "InternalName", "Python DLL\0" - VALUE "LegalCopyright", "Copyright © 2001-2016 Python Software Foundation. Copyright © 2000 BeOpen.com. Copyright © 1995-2001 CNRI. Copyright © 1991-1995 SMC.\0" + VALUE "LegalCopyright", "Copyright © 2001-2017 Python Software Foundation. Copyright © 2000 BeOpen.com. Copyright © 1995-2001 CNRI. Copyright © 1991-1995 SMC.\0" VALUE "OriginalFilename", PYTHON_DLL_NAME "\0" VALUE "ProductName", "Python\0" VALUE "ProductVersion", PYTHON_VERSION diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 0b8f0b8..808d623 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ echo.Fetching external libraries... for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.2d + openssl-1.0.2j tcl-8.6.1.0 tk-8.6.1.0 tix-8.4.3.4 diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 0341368..79b4952 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -20,7 +20,7 @@ $(externalsDir)\sqlite-3.8.11.0 $(externalsDir)\bzip2-1.0.6 $(externalsDir)\xz-5.0.5 - $(externalsDir)\openssl-1.0.2d + $(externalsDir)\openssl-1.0.2j $(externalsDir)\tcltk $(externalsDir)\tcltk64 $(tcltkDir)\lib\tcl86t.lib;$(tcltkDir)\lib\tk86t.lib diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index e0c6685..148a305 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -171,7 +171,7 @@ _lzma Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.2d of the OpenSSL secure sockets + Python wrapper for version 1.0.2j of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 1540d26..1a8cf40 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1014,7 +1014,7 @@ tok_nextc(struct tok_state *tok) else { tok->done = E_OK; tok->inp = strchr(tok->buf, '\0'); - done = tok->inp[-1] == '\n'; + done = tok->inp == tok->buf || tok->inp[-1] == '\n'; } } else { diff --git a/Python/getcopyright.c b/Python/getcopyright.c index c3f1e89..cac647c 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -4,7 +4,7 @@ static const char cprt[] = "\ -Copyright (c) 2001-2016 Python Software Foundation.\n\ +Copyright (c) 2001-2017 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ diff --git a/README b/README index 1ae15a7..2ee032b 100644 --- a/README +++ b/README @@ -1,8 +1,9 @@ -This is Python version 3.4.5 +This is Python version 3.4.6 ============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -2012, 2013, 2014, 2015, 2016 Python Software Foundation. All rights reserved. +2012, 2013, 2014, 2015, 2016, 2017 Python Software Foundation. All rights +reserved. Python 3.x is a new version of the language, which is incompatible with the 2.x line of releases. The language is mostly the same, but many details, especially