Stop traversing dict keys

This commit is contained in:
xmarre 2026-03-16 16:10:01 +01:00
parent a6472b1514
commit 1a00f7743f
2 changed files with 22 additions and 5 deletions

View File

@ -332,10 +332,10 @@ def to_hashable(obj, max_nodes=_MAX_SIGNATURE_CONTAINER_VISITS):
if items is None:
items = list(current.items())
ordered_items = [
(_sanitized_sort_key(k, memo=sort_memo), resolve_value(k), resolve_value(v))
(_sanitized_sort_key(k, memo=sort_memo), k, resolve_value(v))
for k, v in items
]
if any(is_failed(key) or is_failed(value) for _, key, value in ordered_items):
if any(type(key) not in _PRIMITIVE_SIGNATURE_TYPES or is_failed(value) for _, key, value in ordered_items):
memo[current_id] = Unhashable()
continue
ordered_items.sort(key=lambda item: item[0])
@ -398,9 +398,17 @@ def to_hashable(obj, max_nodes=_MAX_SIGNATURE_CONTAINER_VISITS):
memo[current_id] = Unhashable()
active.discard(current_id)
continue
for key, value in reversed(items):
work_stack.append((value, False))
work_stack.append((key, False))
for key, value in items:
if type(key) not in _PRIMITIVE_SIGNATURE_TYPES:
snapshots.pop(current_id, None)
memo[current_id] = Unhashable()
active.discard(current_id)
break
else:
for _, value in reversed(items):
work_stack.append((value, False))
continue
continue
else:
try:
items = list(current)

View File

@ -225,6 +225,15 @@ def test_to_hashable_canonicalizes_dict_insertion_order(caching_module):
assert caching.to_hashable(first) == caching.to_hashable(second)
def test_to_hashable_fails_closed_for_opaque_dict_key(caching_module):
"""Opaque dict keys should fail closed instead of being traversed during hashing."""
caching, _ = caching_module
hashable = caching.to_hashable({_OpaqueValue(): 1})
assert isinstance(hashable, caching.Unhashable)
@pytest.mark.parametrize(
"container_factory",
[