mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	[3.9] bpo-39934: Account for control blocks in 'except' in compiler. (GH-22395) (GH-23303)
* bpo-39934: backport PR 22395 to 3.9
This commit is contained in:
		
							parent
							
								
									05a5d697f4
								
							
						
					
					
						commit
						48a9c0eb2a
					
				
					 3 changed files with 23 additions and 8 deletions
				
			
		|  | @ -946,6 +946,15 @@ def test_empty_line_after_linecont(self): | ||||||
|         except SyntaxError: |         except SyntaxError: | ||||||
|             self.fail("Empty line after a line continuation character is valid.") |             self.fail("Empty line after a line continuation character is valid.") | ||||||
| 
 | 
 | ||||||
|  |     @support.cpython_only | ||||||
|  |     def test_nested_named_except_blocks(self): | ||||||
|  |         code = "" | ||||||
|  |         for i in range(12): | ||||||
|  |             code += f"{'    '*i}try:\n" | ||||||
|  |             code += f"{'    '*(i+1)}raise Exception\n" | ||||||
|  |             code += f"{'    '*i}except Exception as e:\n" | ||||||
|  |         code += f"{' '*4*12}pass" | ||||||
|  |         self._check_error(code, "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 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | Correctly count control blocks in 'except' in compiler. Ensures that a | ||||||
|  | syntax error, rather a fatal error, occurs for deeply nested, named | ||||||
|  | exception handlers. | ||||||
|  | @ -84,8 +84,8 @@ It's called a frame block to distinguish it from a basic block in the | ||||||
| compiler IR. | compiler IR. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END, | enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END, | ||||||
|                   WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE }; |                   WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE, EXCEPTION_HANDLER }; | ||||||
| 
 | 
 | ||||||
| struct fblockinfo { | struct fblockinfo { | ||||||
|     enum fblocktype fb_type; |     enum fblocktype fb_type; | ||||||
|  | @ -1624,9 +1624,7 @@ compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b, | ||||||
| { | { | ||||||
|     struct fblockinfo *f; |     struct fblockinfo *f; | ||||||
|     if (c->u->u_nfblocks >= CO_MAXBLOCKS) { |     if (c->u->u_nfblocks >= CO_MAXBLOCKS) { | ||||||
|         PyErr_SetString(PyExc_SyntaxError, |         return compiler_error(c, "too many statically nested blocks"); | ||||||
|                         "too many statically nested blocks"); |  | ||||||
|         return 0; |  | ||||||
|     } |     } | ||||||
|     f = &c->u->u_fblock[c->u->u_nfblocks++]; |     f = &c->u->u_fblock[c->u->u_nfblocks++]; | ||||||
|     f->fb_type = t; |     f->fb_type = t; | ||||||
|  | @ -1666,6 +1664,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, | ||||||
| { | { | ||||||
|     switch (info->fb_type) { |     switch (info->fb_type) { | ||||||
|         case WHILE_LOOP: |         case WHILE_LOOP: | ||||||
|  |         case EXCEPTION_HANDLER: | ||||||
|             return 1; |             return 1; | ||||||
| 
 | 
 | ||||||
|         case FOR_LOOP: |         case FOR_LOOP: | ||||||
|  | @ -1676,7 +1675,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, | ||||||
|             ADDOP(c, POP_TOP); |             ADDOP(c, POP_TOP); | ||||||
|             return 1; |             return 1; | ||||||
| 
 | 
 | ||||||
|         case EXCEPT: |         case TRY_EXCEPT: | ||||||
|             ADDOP(c, POP_BLOCK); |             ADDOP(c, POP_BLOCK); | ||||||
|             return 1; |             return 1; | ||||||
| 
 | 
 | ||||||
|  | @ -3064,14 +3063,17 @@ compiler_try_except(struct compiler *c, stmt_ty s) | ||||||
|         return 0; |         return 0; | ||||||
|     ADDOP_JREL(c, SETUP_FINALLY, except); |     ADDOP_JREL(c, SETUP_FINALLY, except); | ||||||
|     compiler_use_next_block(c, body); |     compiler_use_next_block(c, body); | ||||||
|     if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL)) |     if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL)) | ||||||
|         return 0; |         return 0; | ||||||
|     VISIT_SEQ(c, stmt, s->v.Try.body); |     VISIT_SEQ(c, stmt, s->v.Try.body); | ||||||
|     ADDOP(c, POP_BLOCK); |     ADDOP(c, POP_BLOCK); | ||||||
|     compiler_pop_fblock(c, EXCEPT, body); |     compiler_pop_fblock(c, TRY_EXCEPT, body); | ||||||
|     ADDOP_JREL(c, JUMP_FORWARD, orelse); |     ADDOP_JREL(c, JUMP_FORWARD, orelse); | ||||||
|     n = asdl_seq_LEN(s->v.Try.handlers); |     n = asdl_seq_LEN(s->v.Try.handlers); | ||||||
|     compiler_use_next_block(c, except); |     compiler_use_next_block(c, except); | ||||||
|  |     /* Runtime will push a block here, so we need to account for that */ | ||||||
|  |     if (!compiler_push_fblock(c, EXCEPTION_HANDLER, NULL, NULL, NULL)) | ||||||
|  |         return 0; | ||||||
|     for (i = 0; i < n; i++) { |     for (i = 0; i < n; i++) { | ||||||
|         excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( |         excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( | ||||||
|             s->v.Try.handlers, i); |             s->v.Try.handlers, i); | ||||||
|  | @ -3156,6 +3158,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) | ||||||
|         } |         } | ||||||
|         compiler_use_next_block(c, except); |         compiler_use_next_block(c, except); | ||||||
|     } |     } | ||||||
|  |     compiler_pop_fblock(c, EXCEPTION_HANDLER, NULL); | ||||||
|     ADDOP(c, RERAISE); |     ADDOP(c, RERAISE); | ||||||
|     compiler_use_next_block(c, orelse); |     compiler_use_next_block(c, orelse); | ||||||
|     VISIT_SEQ(c, stmt, s->v.Try.orelse); |     VISIT_SEQ(c, stmt, s->v.Try.orelse); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Irit Katriel
						Irit Katriel