Skip to content

dict_set_fromkeys() calculates size of dictionary improperly #132762

Open
@ThomasBr0

Description

@ThomasBr0

Bug report

Bug description:

The function dict_set_fromkeys() in the file dictobject.c adds elements of an iterable to an existing dictionary. The size of the expanded dictionary is estimated as PySet_GET_SIZE(iterable) and the size of the existing dictionary is not considered.

This is unlogical.

A more resonable estimation is "mp->ma_used + PySet_GET_SIZE(iterable)". What turns this into a bug is the fact that a large dictionary plus a small iterable can cause the function to loop forever.

The following code is adopted from the official tests, file test_dict.py. Official binaries for Python 3.13.3 compiled with MSVC will loop forever when running this modified test (the official test has range(10)). Other platforms may be affected as well.

class baddict3(dict):
    def __new__(cls):
        return d
d = {i : i for i in range(17)}
res = d.copy()
res.update(a=None, b=None, c=None)
print(res)
q = baddict3.fromkeys({"a", "b", "c"})
print(q)

A minor error is in the function calculate_log2_keysize(minsize) which has three branches for calculating its result. However, when minsize < 10 the results of the three branches can differ. Since _BitScanReverse64() is Windows-only other platforms might be unaffected.

A final unrelated note. PEP 11 – CPython platform support states that aarch64-unknown-linux-gnu and x86_64-unknown-linux-gnu are Tier 1 AND Tier 2.

CPython versions tested on:

3.13

Operating systems tested on:

Windows

Metadata

Metadata

Assignees

Labels

3.13bugs and security fixes3.14new features, bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions