Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f256afe
Fix undefined behavior in listiter_reduce from _PyEval_GetBuiltin sid…
ionite34 Feb 10, 2023
6b4faad
Update comment to not mention `__eq__`
ionite34 Feb 10, 2023
a6d6211
Fix undefined behavior in iter_reduce and calliter_reduce
ionite34 Feb 10, 2023
4ccf427
Update listiter_reduce_general comment
ionite34 Feb 10, 2023
c2c9cfb
Fix undefined behavior in bytearrayiter_reduce from _PyEval_GetBuilti…
ionite34 Feb 10, 2023
e2989d9
Fix undefined behavior in striter_reduce from _PyEval_GetBuiltin side…
ionite34 Feb 10, 2023
71960a8
Fix undefined behavior in tupleiter_reduce from _PyEval_GetBuiltin si…
ionite34 Feb 10, 2023
efa0540
Move iter call in unicodeiter_reduce before `it` pointer access due t…
ionite34 Feb 10, 2023
c5abb14
Add iter reduce tests for issue #101765
ionite34 Feb 10, 2023
45522c6
Remove C++ reference in comments
ionite34 Feb 10, 2023
4f5fc19
Remove C++ reference in comments
ionite34 Feb 10, 2023
049a8dd
Move builtin declarations inside if blocks
ionite34 Feb 10, 2023
ef4f955
Move _PyEval_GetBuiltin before gi checks, add gi NULL check in ga_ite…
ionite34 Feb 10, 2023
7d4afb0
Update iter reduce mutating tests for generic alias
ionite34 Feb 10, 2023
8e4418d
📜🤖 Added by blurb_it.
blurb-it[bot] Feb 10, 2023
d8ced8e
Fix backticks format for news
ionite34 Feb 10, 2023
178b8ea
Refactor iter reduce builtins mutation tests
ionite34 Feb 10, 2023
49ba8c3
Update iter mutating builtins test to include reversed iterator for l…
ionite34 Feb 10, 2023
93854e1
Add comment in unicodeiter_reduce for moving iter call before it poin…
ionite34 Feb 10, 2023
98ec3c6
Change test `__builtins__` to builtins import
ionite34 Feb 10, 2023
e661495
Change NEWS blurb phrasing
ionite34 Feb 10, 2023
19ab9c6
Update iter reduce mutating builtins test comments and simplify logic
ionite34 Feb 10, 2023
9b664c2
Update comments to better reflect issue
ionite34 Feb 24, 2023
c67b11a
Clarify test comments
ionite34 Feb 24, 2023
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
Prev Previous commit
Next Next commit
Update iter mutating builtins test to include reversed iterator for l…
…ist conditional branch
  • Loading branch information
ionite34 committed Feb 10, 2023
commit 49ba8c3bfc09e026970bc4fa842c466dcee7d0f5
54 changes: 38 additions & 16 deletions Lib/test/test_iter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from test.support import check_free_after_iterating, ALWAYS_EQ, NEVER_EQ
import pickle
import collections.abc
import functools
import contextlib

# Test result of triple loop (too big to inline)
TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
Expand Down Expand Up @@ -249,29 +251,34 @@ def test_reduce_mutating_builtins_iter(self):
# where iter `__reduce__` calls could lead to a segfault or SystemError
# depending on the order of C argument evaluation, which is undefined

# Backup builtins.iter
# Backup builtins
builtins = __builtins__
orig_iter = builtins["iter"]
orig = {"iter": iter, "reversed": reversed}

def run(item, init=None, sentinel=None):
def run(builtin_name, item, init=None, sentinel=None):
if init is not None:
args = init if isinstance(init, tuple) else (init,)
Comment thread
carljm marked this conversation as resolved.
Outdated
item = item(*args)
it = iter(item) if sentinel is None else iter(item, sentinel)

class CustomStr:
def __init__(self, name, iterator):
self.name = name
self.iterator = iterator
def __hash__(self):
return hash("iter")
return hash(self.name)
def __eq__(self, other):
# Here we exhaust `it`, possibly changing our `it_seq` pointer to NULL
# The `__reduce__` call should correctly get the pointers after this call
list(it)
return other == "iter"
# Here we exhaust our iterator, possibly changing
# its `it_seq` pointer to NULL
# The `__reduce__` call should correctly get
# the pointers after this call
list(self.iterator)
return other == self.name

# del is required here
# to avoid calling the last test case's custom __eq__
del builtins["iter"]
builtins[CustomStr()] = orig_iter
del builtins[builtin_name]
builtins[CustomStr(builtin_name, it)] = orig[builtin_name]

return it.__reduce__()

Expand All @@ -285,19 +292,34 @@ def __eq__(self, other):
]

try:
run_iter = functools.partial(run, "iter")
# The returned value of `__reduce__` should not only be valid
# but also *empty*, as `it` was exhausted during `__eq__`
# i.e "xyz" returns (iter, ("",))
self.assertEqual(run(str, "xyz"), (orig_iter, ("",)))
self.assertEqual(run(list, range(8)), (orig_iter, ([],)))
self.assertEqual(run_iter(str, "xyz"), (orig["iter"], ("",)))
self.assertEqual(run_iter(list, range(8)), (orig["iter"], ([],)))

# _PyEval_GetBuiltin is also called for `reversed` in a branch of
# listiter_reduce_general
self.assertEqual(
run("reversed", orig["reversed"], list(range(8))),
(iter, ([],))
)

for case in types:
self.assertEqual(run(*case), (orig_iter, ((),)))
self.assertEqual(run_iter(*case), (orig["iter"], ((),)))
finally:
# del is required here
# to avoid calling our custom __eq__
del builtins["iter"]
# Restore original iter
builtins["iter"] = orig_iter
# we also need to supress KeyErrors in case
Comment thread
carljm marked this conversation as resolved.
Outdated
# a failed test deletes the key without setting anything
with contextlib.suppress(KeyError):
del builtins["iter"]
with contextlib.suppress(KeyError):
del builtins["reversed"]
# Restore original builtins
for key, func in orig.items():
builtins[key] = func

# Test a new_style class with __iter__ but no next() method
def test_new_style_iter_class(self):
Expand Down