Description
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