https://github.com/python/cpython/commit/8e1f26e4f06c43cf52afa26ce30f27d2c1…
commit: 8e1f26e4f06c43cf52afa26ce30f27d2c1129c4a
branch: master
author: Борис Верховский <boris.verk(a)gmail.com>
committer: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
date: 2019-12-31T04:28:18-08:00
summary:
Minor doc fixes in urllib.parse (GH-17745)
files:
M Doc/library/urllib.parse.rst
diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst
index 2d4d5a9e60969..02f0c01e224dd 100644
--- a/Doc/library/urllib.parse.rst
+++ b/Doc/library/urllib.parse.rst
@@ -42,8 +42,8 @@ or on combining URL components into a URL string.
Parse a URL into six components, returning a 6-item :term:`named tuple`. This
corresponds to the general structure of a URL:
``scheme://netloc/path;parameters?query#fragment``.
- Each tuple item is a string, possibly empty. The components are not broken up in
- smaller parts (for example, the network location is a single string), and %
+ Each tuple item is a string, possibly empty. The components are not broken up
+ into smaller parts (for example, the network location is a single string), and %
escapes are not expanded. The delimiters as shown above are not part of the
result, except for a leading slash in the *path* component, which is retained if
present. For example:
@@ -328,22 +328,22 @@ or on combining URL components into a URL string.
.. note::
- If *url* is an absolute URL (that is, starting with ``//`` or ``scheme://``),
- the *url*'s host name and/or scheme will be present in the result. For example:
+ If *url* is an absolute URL (that is, it starts with ``//`` or ``scheme://``),
+ the *url*'s hostname and/or scheme will be present in the result. For example:
- .. doctest::
+ .. doctest::
- >>> urljoin('http://www.cwi.nl/%7Eguido/Python.html',
- ... '//www.python.org/%7Eguido')
- 'http://www.python.org/%7Eguido'
+ >>> urljoin('http://www.cwi.nl/%7Eguido/Python.html',
+ ... '//www.python.org/%7Eguido')
+ 'http://www.python.org/%7Eguido'
- If you do not want that behavior, preprocess the *url* with :func:`urlsplit` and
- :func:`urlunsplit`, removing possible *scheme* and *netloc* parts.
+ If you do not want that behavior, preprocess the *url* with :func:`urlsplit` and
+ :func:`urlunsplit`, removing possible *scheme* and *netloc* parts.
.. versionchanged:: 3.5
- Behaviour updated to match the semantics defined in :rfc:`3986`.
+ Behavior updated to match the semantics defined in :rfc:`3986`.
.. function:: urldefrag(url)
@@ -521,11 +521,11 @@ task isn't already covered by the URL parsing functions above.
Replace special characters in *string* using the ``%xx`` escape. Letters,
digits, and the characters ``'_.-~'`` are never quoted. By default, this
- function is intended for quoting the path section of URL. The optional *safe*
- parameter specifies additional ASCII characters that should not be quoted
- --- its default value is ``'/'``.
+ function is intended for quoting the path section of a URL. The optional
+ *safe* parameter specifies additional ASCII characters that should not be
+ quoted --- its default value is ``'/'``.
- *string* may be either a :class:`str` or a :class:`bytes`.
+ *string* may be either a :class:`str` or a :class:`bytes` object.
.. versionchanged:: 3.7
Moved from :rfc:`2396` to :rfc:`3986` for quoting URL strings. "~" is now
@@ -547,7 +547,7 @@ task isn't already covered by the URL parsing functions above.
.. function:: quote_plus(string, safe='', encoding=None, errors=None)
- Like :func:`quote`, but also replace spaces by plus signs, as required for
+ Like :func:`quote`, but also replace spaces with plus signs, as required for
quoting HTML form values when building up a query string to go into a URL.
Plus signs in the original string are escaped unless they are included in
*safe*. It also does not have *safe* default to ``'/'``.
@@ -566,12 +566,12 @@ task isn't already covered by the URL parsing functions above.
.. function:: unquote(string, encoding='utf-8', errors='replace')
- Replace ``%xx`` escapes by their single-character equivalent.
+ Replace ``%xx`` escapes with their single-character equivalent.
The optional *encoding* and *errors* parameters specify how to decode
percent-encoded sequences into Unicode characters, as accepted by the
:meth:`bytes.decode` method.
- *string* may be either a :class:`str` or a :class:`bytes`.
+ *string* may be either a :class:`str` or a :class:`bytes` object.
*encoding* defaults to ``'utf-8'``.
*errors* defaults to ``'replace'``, meaning invalid sequences are replaced
@@ -587,8 +587,8 @@ task isn't already covered by the URL parsing functions above.
.. function:: unquote_plus(string, encoding='utf-8', errors='replace')
- Like :func:`unquote`, but also replace plus signs by spaces, as required for
- unquoting HTML form values.
+ Like :func:`unquote`, but also replace plus signs with spaces, as required
+ for unquoting HTML form values.
*string* must be a :class:`str`.
@@ -597,10 +597,10 @@ task isn't already covered by the URL parsing functions above.
.. function:: unquote_to_bytes(string)
- Replace ``%xx`` escapes by their single-octet equivalent, and return a
+ Replace ``%xx`` escapes with their single-octet equivalent, and return a
:class:`bytes` object.
- *string* may be either a :class:`str` or a :class:`bytes`.
+ *string* may be either a :class:`str` or a :class:`bytes` object.
If it is a :class:`str`, unescaped non-ASCII characters in *string*
are encoded into UTF-8 bytes.
@@ -631,7 +631,7 @@ task isn't already covered by the URL parsing functions above.
When a sequence of two-element tuples is used as the *query*
argument, the first element of each tuple is a key and the second is a
value. The value element in itself can be a sequence and in that case, if
- the optional parameter *doseq* is evaluates to ``True``, individual
+ the optional parameter *doseq* evaluates to ``True``, individual
``key=value`` pairs separated by ``'&'`` are generated for each element of
the value sequence for the key. The order of parameters in the encoded
string will match the order of parameter tuples in the sequence.
@@ -643,11 +643,12 @@ task isn't already covered by the URL parsing functions above.
To reverse this encoding process, :func:`parse_qs` and :func:`parse_qsl` are
provided in this module to parse query strings into Python data structures.
- Refer to :ref:`urllib examples <urllib-examples>` to find out how urlencode
- method can be used for generating query string for a URL or data for POST.
+ Refer to :ref:`urllib examples <urllib-examples>` to find out how the
+ :func:`urllib.parse.urlencode` method can be used for generating the query
+ string of a URL or data for a POST request.
.. versionchanged:: 3.2
- Query parameter supports bytes and string objects.
+ *query* supports bytes and string objects.
.. versionadded:: 3.5
*quote_via* parameter.
https://github.com/python/cpython/commit/53f11ba7b1498133ce3ff8173d5ae2e018…
commit: 53f11ba7b1498133ce3ff8173d5ae2e0182a3603
branch: 3.7
author: Dong-hee Na <donghee.na92(a)gmail.com>
committer: Pablo Galindo <Pablogsal(a)gmail.com>
date: 2019-12-31T04:15:10Z
summary:
[3.7] bpo-38588: Fix possible crashes in dict and list when calling P… (GH-17765)
* [3.7] bpo-38588: Fix possible crashes in dict and list when calling PyObject_RichCompareBool (GH-17734)
Take strong references before calling PyObject_RichCompareBool to protect against the case
where the object dies during the call..
(cherry picked from commit 2d5bf568eaa5059402ccce9ba5a366986ba27c8a)
Co-authored-by: Dong-hee Na <donghee.na92(a)gmail.com>
* methane's suggestion
methane's suggestion
Co-Authored-By: Inada Naoki <songofacandy(a)gmail.com>
Co-authored-by: Inada Naoki <songofacandy(a)gmail.com>
files:
A Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst
M Lib/test/test_dict.py
M Lib/test/test_list.py
M Objects/dictobject.c
M Objects/listobject.c
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index 90c0a3131a78e..ea9dcb6a81c6a 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -1138,7 +1138,7 @@ def test_free_after_iterating(self):
support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
def test_equal_operator_modifying_operand(self):
- # test fix for seg fault reported in issue 27945 part 3.
+ # test fix for seg fault reported in bpo-27945 part 3.
class X():
def __del__(self):
dict_b.clear()
@@ -1154,6 +1154,16 @@ def __hash__(self):
dict_b = {X(): X()}
self.assertTrue(dict_a == dict_b)
+ # test fix for seg fault reported in bpo-38588 part 1.
+ class Y:
+ def __eq__(self, other):
+ dict_d.clear()
+ return True
+
+ dict_c = {0: Y()}
+ dict_d = {0: set()}
+ self.assertTrue(dict_c == dict_d)
+
def test_fromkeys_operator_modifying_dict_operand(self):
# test fix for seg fault reported in issue 27945 part 4a.
class X(int):
diff --git a/Lib/test/test_list.py b/Lib/test/test_list.py
index ece4598e4eaf2..553ac8c1cef81 100644
--- a/Lib/test/test_list.py
+++ b/Lib/test/test_list.py
@@ -162,6 +162,31 @@ class L(list): pass
with self.assertRaises(TypeError):
(3,) + L([1,2])
+ def test_equal_operator_modifying_operand(self):
+ # test fix for seg fault reported in bpo-38588 part 2.
+ class X:
+ def __eq__(self,other) :
+ list2.clear()
+ return NotImplemented
+
+ class Y:
+ def __eq__(self, other):
+ list1.clear()
+ return NotImplemented
+
+ class Z:
+ def __eq__(self, other):
+ list3.clear()
+ return NotImplemented
+
+ list1 = [X()]
+ list2 = [Y()]
+ self.assertTrue(list1 == list2)
+
+ list3 = [Z()]
+ list4 = [1]
+ self.assertFalse(list3 == list4)
+
def test_count_index_remove_crashes(self):
# bpo-38610: The count(), index(), and remove() methods were not
# holding strong references to list elements while calling
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst
new file mode 100644
index 0000000000000..0b81085a89d25
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst
@@ -0,0 +1,2 @@
+Fix possible crashes in dict and list when calling
+:c:func:`PyObject_RichCompareBool`.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 9437448849007..3f00002a8991a 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -2677,9 +2677,11 @@ dict_equal(PyDictObject *a, PyDictObject *b)
return -1;
return 0;
}
+ Py_INCREF(bval);
cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
Py_DECREF(key);
Py_DECREF(aval);
+ Py_DECREF(bval);
if (cmp <= 0) /* error or not equal */
return cmp;
}
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 724f25677a16e..d622da9e0dbf3 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2615,8 +2615,18 @@ list_richcompare(PyObject *v, PyObject *w, int op)
/* Search for the first index where items are different */
for (i = 0; i < Py_SIZE(vl) && i < Py_SIZE(wl); i++) {
+ PyObject *vitem = vl->ob_item[i];
+ PyObject *witem = wl->ob_item[i];
+ if (vitem == witem) {
+ continue;
+ }
+
+ Py_INCREF(vitem);
+ Py_INCREF(witem);
int k = PyObject_RichCompareBool(vl->ob_item[i],
wl->ob_item[i], Py_EQ);
+ Py_DECREF(vitem);
+ Py_DECREF(witem);
if (k < 0)
return NULL;
if (!k)