mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	gh-113297: Fix segfault in compiler for with statement with 19 context managers (#113327)
This commit is contained in:
		
							parent
							
								
									9afb0e1606
								
							
						
					
					
						commit
						c31943af16
					
				
					 3 changed files with 29 additions and 1 deletions
				
			
		| 
						 | 
					@ -2017,6 +2017,7 @@ def f(x: *b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import doctest
 | 
					import doctest
 | 
				
			||||||
 | 
					import textwrap
 | 
				
			||||||
import unittest
 | 
					import unittest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from test import support
 | 
					from test import support
 | 
				
			||||||
| 
						 | 
					@ -2279,6 +2280,31 @@ def test_nested_named_except_blocks(self):
 | 
				
			||||||
        code += f"{' '*4*12}pass"
 | 
					        code += f"{' '*4*12}pass"
 | 
				
			||||||
        self._check_error(code, "too many statically nested blocks")
 | 
					        self._check_error(code, "too many statically nested blocks")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @support.cpython_only
 | 
				
			||||||
 | 
					    def test_with_statement_many_context_managers(self):
 | 
				
			||||||
 | 
					        # See gh-113297
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def get_code(n):
 | 
				
			||||||
 | 
					            code = textwrap.dedent("""
 | 
				
			||||||
 | 
					                def bug():
 | 
				
			||||||
 | 
					                    with (
 | 
				
			||||||
 | 
					                    a
 | 
				
			||||||
 | 
					                """)
 | 
				
			||||||
 | 
					            for i in range(n):
 | 
				
			||||||
 | 
					                code += f"    as a{i}, a\n"
 | 
				
			||||||
 | 
					            code += "): yield a"
 | 
				
			||||||
 | 
					            return code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CO_MAXBLOCKS = 20  # static nesting limit of the compiler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for n in range(CO_MAXBLOCKS):
 | 
				
			||||||
 | 
					            with self.subTest(f"within range: {n=}"):
 | 
				
			||||||
 | 
					                compile(get_code(n), "<string>", "exec")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for n in range(CO_MAXBLOCKS, CO_MAXBLOCKS + 5):
 | 
				
			||||||
 | 
					            with self.subTest(f"out of range: {n=}"):
 | 
				
			||||||
 | 
					                self._check_error(get_code(n), "too many statically nested blocks")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_barry_as_flufl_with_syntax_errors(self):
 | 
					    def test_barry_as_flufl_with_syntax_errors(self):
 | 
				
			||||||
        # The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
 | 
					        # The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
 | 
				
			||||||
        # is reading the wrong token in the presence of syntax errors later
 | 
					        # is reading the wrong token in the presence of syntax errors later
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Fix segfault in the compiler on with statement with 19 context managers.
 | 
				
			||||||
| 
						 | 
					@ -648,7 +648,7 @@ mark_except_handlers(basicblock *entryblock) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct _PyCfgExceptStack {
 | 
					struct _PyCfgExceptStack {
 | 
				
			||||||
    basicblock *handlers[CO_MAXBLOCKS+1];
 | 
					    basicblock *handlers[CO_MAXBLOCKS+2];
 | 
				
			||||||
    int depth;
 | 
					    int depth;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -661,6 +661,7 @@ push_except_block(struct _PyCfgExceptStack *stack, cfg_instr *setup) {
 | 
				
			||||||
    if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) {
 | 
					    if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) {
 | 
				
			||||||
        target->b_preserve_lasti = 1;
 | 
					        target->b_preserve_lasti = 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    assert(stack->depth <= CO_MAXBLOCKS);
 | 
				
			||||||
    stack->handlers[++stack->depth] = target;
 | 
					    stack->handlers[++stack->depth] = target;
 | 
				
			||||||
    return target;
 | 
					    return target;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue