bpo-41531: Fix compilation of dict literals with more than 0xFFFF ele… · python/cpython@d64d78b

File tree

3 files changed

lines changed

  • Misc/NEWS.d/next/Core and Builtins

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -750,6 +750,16 @@ def continue_in_while():

750750

self.assertEqual(None, opcodes[0].argval)

751751

self.assertEqual('RETURN_VALUE', opcodes[1].opname)

752752
753+

def test_big_dict_literal(self):

754+

# The compiler has a flushing point in "compiler_dict" that calls compiles

755+

# a portion of the dictionary literal when the loop that iterates over the items

756+

# reaches 0xFFFF elements but the code was not including the boundary element,

757+

# dropping the key at position 0xFFFF. See bpo-41531 for more information

758+
759+

dict_size = 0xFFFF + 1

760+

the_dict = "{" + ",".join(f"{x}:{x}" for x in range(dict_size)) + "}"

761+

self.assertEqual(len(eval(the_dict)), dict_size)

762+
753763

class TestExpressionStackSize(unittest.TestCase):

754764

# These tests check that the computed stack size for a code object

755765

# stays within reasonable bounds (see issue #21523 for an example

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,2 @@

1+

Fix a bug that was dropping keys when compiling dict literals with more than

2+

0xFFFF elements. Patch by Pablo Galindo.

Original file line numberDiff line numberDiff line change

@@ -3890,7 +3890,7 @@ compiler_dict(struct compiler *c, expr_ty e)

38903890

}

38913891

else {

38923892

if (elements == 0xFFFF) {

3893-

if (!compiler_subdict(c, e, i - elements, i)) {

3893+

if (!compiler_subdict(c, e, i - elements, i + 1)) {

38943894

return 0;

38953895

}

38963896

if (have_dict) {