Mailing List Archive

bpo-27946: Fix possible crash in ElementTree.Element (GH-29915)
https://github.com/python/cpython/commit/d15cdb2f32f572ce56d7120135da24b9fdce4c99
commit: d15cdb2f32f572ce56d7120135da24b9fdce4c99
branch: main
author: Serhiy Storchaka <storchaka@gmail.com>
committer: serhiy-storchaka <storchaka@gmail.com>
date: 2021-12-05T14:22:54+02:00
summary:

bpo-27946: Fix possible crash in ElementTree.Element (GH-29915)

Getting an attribute via attrib.get() simultaneously with replacing
the attrib dict can lead to access to deallocated dict.

files:
A Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
M Lib/test/test_xml_etree_c.py
M Modules/_elementtree.c

diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index e68613bb910dd..bec8208571902 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -169,6 +169,18 @@ def test_xmlpullparser_leaks(self):
del parser
support.gc_collect()

+ def test_dict_disappearing_during_get_item(self):
+ # test fix for seg fault reported in issue 27946
+ class X:
+ def __hash__(self):
+ e.attrib = {} # this frees e->extra->attrib
+ [{i: i} for i in range(1000)] # exhaust the dict keys cache
+ return 13
+
+ e = cET.Element("elem", {1: 2})
+ r = e.get(X())
+ self.assertIsNone(r)
+

@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
new file mode 100644
index 0000000000000..0378efca746bb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
@@ -0,0 +1,3 @@
+Fix possible crash when getting an attribute of
+class:`xml.etree.ElementTree.Element` simultaneously with
+replacing the ``attrib`` dict.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index b4528a90b3e09..9dadeef712938 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -1393,22 +1393,19 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key,
PyObject *default_value)
/*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/
{
- PyObject* value;
-
- if (!self->extra || !self->extra->attrib)
- value = default_value;
- else {
- value = PyDict_GetItemWithError(self->extra->attrib, key);
- if (!value) {
- if (PyErr_Occurred()) {
- return NULL;
- }
- value = default_value;
+ if (self->extra && self->extra->attrib) {
+ PyObject *attrib = self->extra->attrib;
+ Py_INCREF(attrib);
+ PyObject *value = PyDict_GetItemWithError(attrib, key);
+ Py_XINCREF(value);
+ Py_DECREF(attrib);
+ if (value != NULL || PyErr_Occurred()) {
+ return value;
}
}

- Py_INCREF(value);
- return value;
+ Py_INCREF(default_value);
+ return default_value;
}

static PyObject *

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins
bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) [ In reply to ]
https://github.com/python/cpython/commit/52a9a71fe682e47f6c78a9c34aa9a797ca632c86
commit: 52a9a71fe682e47f6c78a9c34aa9a797ca632c86
branch: 3.9
author: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
committer: miss-islington <31488909+miss-islington@users.noreply.github.com>
date: 2021-12-05T11:04:59-08:00
summary:

bpo-27946: Fix possible crash in ElementTree.Element (GH-29915)


Getting an attribute via attrib.get() simultaneously with replacing
the attrib dict can lead to access to deallocated dict.
(cherry picked from commit d15cdb2f32f572ce56d7120135da24b9fdce4c99)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

files:
A Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
M Lib/test/test_xml_etree_c.py
M Modules/_elementtree.c

diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index e26e1714a540b..82cedfd00a55d 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -169,6 +169,18 @@ def test_xmlpullparser_leaks(self):
del parser
support.gc_collect()

+ def test_dict_disappearing_during_get_item(self):
+ # test fix for seg fault reported in issue 27946
+ class X:
+ def __hash__(self):
+ e.attrib = {} # this frees e->extra->attrib
+ [{i: i} for i in range(1000)] # exhaust the dict keys cache
+ return 13
+
+ e = cET.Element("elem", {1: 2})
+ r = e.get(X())
+ self.assertIsNone(r)
+

@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
new file mode 100644
index 0000000000000..0378efca746bb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
@@ -0,0 +1,3 @@
+Fix possible crash when getting an attribute of
+class:`xml.etree.ElementTree.Element` simultaneously with
+replacing the ``attrib`` dict.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 67a00a3413b1d..d9c2a23ccb858 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -1393,22 +1393,19 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key,
PyObject *default_value)
/*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/
{
- PyObject* value;
-
- if (!self->extra || !self->extra->attrib)
- value = default_value;
- else {
- value = PyDict_GetItemWithError(self->extra->attrib, key);
- if (!value) {
- if (PyErr_Occurred()) {
- return NULL;
- }
- value = default_value;
+ if (self->extra && self->extra->attrib) {
+ PyObject *attrib = self->extra->attrib;
+ Py_INCREF(attrib);
+ PyObject *value = PyDict_GetItemWithError(attrib, key);
+ Py_XINCREF(value);
+ Py_DECREF(attrib);
+ if (value != NULL || PyErr_Occurred()) {
+ return value;
}
}

- Py_INCREF(value);
- return value;
+ Py_INCREF(default_value);
+ return default_value;
}

static PyObject *

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins
bpo-27946: Fix possible crash in ElementTree.Element (GH-29915) [ In reply to ]
https://github.com/python/cpython/commit/beb834292db54fea129dd073cc822179430cee52
commit: beb834292db54fea129dd073cc822179430cee52
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
committer: miss-islington <31488909+miss-islington@users.noreply.github.com>
date: 2021-12-05T11:04:52-08:00
summary:

bpo-27946: Fix possible crash in ElementTree.Element (GH-29915)


Getting an attribute via attrib.get() simultaneously with replacing
the attrib dict can lead to access to deallocated dict.
(cherry picked from commit d15cdb2f32f572ce56d7120135da24b9fdce4c99)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

files:
A Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
M Lib/test/test_xml_etree_c.py
M Modules/_elementtree.c

diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index e68613bb910dd..bec8208571902 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -169,6 +169,18 @@ def test_xmlpullparser_leaks(self):
del parser
support.gc_collect()

+ def test_dict_disappearing_during_get_item(self):
+ # test fix for seg fault reported in issue 27946
+ class X:
+ def __hash__(self):
+ e.attrib = {} # this frees e->extra->attrib
+ [{i: i} for i in range(1000)] # exhaust the dict keys cache
+ return 13
+
+ e = cET.Element("elem", {1: 2})
+ r = e.get(X())
+ self.assertIsNone(r)
+

@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
new file mode 100644
index 0000000000000..0378efca746bb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-12-04-20-08-42.bpo-27946.-Vuarf.rst
@@ -0,0 +1,3 @@
+Fix possible crash when getting an attribute of
+class:`xml.etree.ElementTree.Element` simultaneously with
+replacing the ``attrib`` dict.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index b4528a90b3e09..9dadeef712938 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -1393,22 +1393,19 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key,
PyObject *default_value)
/*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/
{
- PyObject* value;
-
- if (!self->extra || !self->extra->attrib)
- value = default_value;
- else {
- value = PyDict_GetItemWithError(self->extra->attrib, key);
- if (!value) {
- if (PyErr_Occurred()) {
- return NULL;
- }
- value = default_value;
+ if (self->extra && self->extra->attrib) {
+ PyObject *attrib = self->extra->attrib;
+ Py_INCREF(attrib);
+ PyObject *value = PyDict_GetItemWithError(attrib, key);
+ Py_XINCREF(value);
+ Py_DECREF(attrib);
+ if (value != NULL || PyErr_Occurred()) {
+ return value;
}
}

- Py_INCREF(value);
- return value;
+ Py_INCREF(default_value);
+ return default_value;
}

static PyObject *

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins