Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-126033: fix a crash inxml.etree.ElementTree.Element.remove when concurrent mutations happen#126124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
picnixz merged 31 commits intopython:mainfrompicnixz:fix/xml-evil-remove-126033
Mar 31, 2025
Merged
Changes from1 commit
Commits
Show all changes
31 commits
Select commitHold shift + click to select a range
abc121c
Add versioning to XML elements.
picnixzOct 27, 2024
4efa517
fix tests
picnixzOct 27, 2024
4ca3cf0
fix portability issues
picnixzOct 27, 2024
a1950d1
fixup
picnixzOct 28, 2024
9b6f559
unify versioning
picnixzOct 29, 2024
00a7a7e
handle evil mutations in `Element.remove`
picnixzOct 29, 2024
59ade8f
blurb
picnixzOct 29, 2024
7fc9932
improve NEWS entry formulation
picnixzDec 6, 2024
e30756d
remove versioning
picnixzDec 8, 2024
f2b5bb1
fix tests
picnixzDec 8, 2024
9f73517
improve detection and tests
picnixzDec 15, 2024
70f2aad
revert whitespaces
picnixzDec 15, 2024
756b1eb
amend NEWS
picnixzDec 17, 2024
4b74caf
improve test coverage
picnixzDec 17, 2024
fd29203
align C implementation with Python implementation as much as possible
picnixzDec 17, 2024
e7033b6
fix tests and improve coverage
picnixzDec 17, 2024
4d3cdd7
fix tests (i'll explain afterwards)
picnixzDec 17, 2024
883e8d2
improve comments
picnixzDec 17, 2024
220b669
change root name to avoid special wildcards
picnixzDec 19, 2024
7f26430
avoid strong reference on the child to remove
picnixzDec 19, 2024
e8d84c8
address Serhiy's review
picnixzDec 19, 2024
3a43c0f
Merge branch 'main' into fix/xml-evil-remove-126033
picnixzJan 19, 2025
bc52c04
Update Misc/NEWS.d/next/Library/2024-10-29-12-59-45.gh-issue-126033.s…
picnixzFeb 4, 2025
f4a4dae
remove un-necessary subtest parameter
picnixzFeb 8, 2025
09a9fa9
Reduce the visual size of the tests
picnixzFeb 8, 2025
f5d352f
fixup docs
picnixzFeb 8, 2025
2b47468
Merge branch 'main' into fix/xml-evil-remove-126033
picnixzFeb 8, 2025
dc576ab
Merge branch 'main' into fix/xml-evil-remove-126033
picnixzFeb 22, 2025
ce66ac7
Merge branch 'main' into fix/xml-evil-remove-126033
picnixzMar 14, 2025
04cb600
do not pedantically test the pure Python implementation
picnixzMar 15, 2025
a0c2324
Merge branch 'main' into fix/xml-evil-remove-126033
picnixzMar 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
do not pedantically test the pure Python implementation
  • Loading branch information
@picnixz
picnixz committedMar 15, 2025
commit04cb600a784440c826163e7fcf1f81a97cffe296
73 changes: 13 additions & 60 deletionsLib/test/test_xml_etree.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2772,67 +2772,20 @@ def __eq__(self, o):
g.assert_not_called()

# Test removing root[1] (of type R) from [U(), R()].
#
# In pure Python, using root.clear() sets the children
# list to [] without calling list.clear().
#
# For this reason, the call to root.remove() first
# checks root[0] and sets the children list to []
# since either root[0] or root[1] is an evil element.
#
# Since checking root[1] still uses the old reference
# to the children list, PyObject_RichCompareBool() branches
# to the fast Py_EQ path and Y.__eq__() is called exactly
# once (when checking root[0]).
#
# NOTE(picnixz): the Python and C implementations
# could be aligned if 'self._children = []' is
# replaced by 'self._children.clear()'; however,
# this should be carefully addressed since any
# reference to 'self._children' will be affected.
is_special = is_python_implementation() and raises and Z is Y
if is_special:
def check(f, never, arg0spec, arg1spec):
never.assert_not_called()
f.assert_called_once()

arg0cls, arg0tag = arg0spec
self.assertIs(f.call_args[0][0].__class__, arg0cls)
self.assertIs(f.call_args[0][0].tag, arg0tag)

arg1cls, arg1tag = arg1spec
self.assertIs(f.call_args[0][1].__class__, arg1cls)
self.assertIs(f.call_args[0][1].tag, arg1tag)

with self.subTest("remove root[1] from [E(), Z()]"):
root = E('top')
root.extend([E('one'), Z('rem')])
with equal_wrapper(E) as never, equal_wrapper(Z) as f:
root.remove(root[1])
# Calling PyObject_RichCompareBool(root[0], root[1], Py_EQ)
# delegates to Z.__eq__(root[1], root[0]) since E.__eq__ is
# not implemented. In particular, E.__eq__ is never called
# but Z.__eq__ is called when checking root[0].
check(f, never, (Z, 'rem'), (E, 'one'))

with self.subTest("remove root[1] from [Z(), E()]"):
root = E('top')
root.extend([Z('one'), E('rem')])
with equal_wrapper(E) as never, equal_wrapper(Z) as f:
root.remove(root[1])
# Calling PyObject_RichCompareBool(root[0], root[1], Py_EQ)
# delegates to Z.__eq__(root[0], root[1]). In particular,
# E.__eq__ is never called due to the Py_EQ fast path.
check(f, never, (Z, 'one'), (E, 'rem'))

with self.subTest("remove root[1] from [Z(), Z()]"):
root = E('top')
root.extend([Z('one'), Z('rem')])
self.assertNotEqual(list(root), [])
with equal_wrapper(E) as never, equal_wrapper(Z) as f:
root.remove(root[1])
# Same arguments as for the [Z(), E()] case.
check(f, never, (Z, 'one'), (Z, 'rem'))
if is_python_implementation() and raises and Z is Y:
# In pure Python, using root.clear() sets the children
# list to [] without calling list.clear().
#
# For this reason, the call to root.remove() first
# checks root[0] and sets the children list to []
# since either root[0] or root[1] is an evil element.
#
# Since checking root[1] still uses the old reference
# to the children list, PyObject_RichCompareBool() branches
# to the fast Py_EQ path and Y.__eq__() is called exactly
# once (when checking root[0]).
continue
else:
cases = self.cases_for_remove_existing_with_mutations(E, Z)
for R, U, description in cases:
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp