mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	[3.9] bpo-42218: Correctly handle errors in left-recursive rules (GH-23065) (GH-23066)
Left-recursive rules need to check for errors explicitly, since
even if the rule returns NULL, the parsing might continue and lead
to long-distance failures.
Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
(cherry picked from commit 02cdfc93f8)
Automerge-Triggered-By: GH:lysnikolaou
			
			
This commit is contained in:
		
							parent
							
								
									dbaa07db67
								
							
						
					
					
						commit
						cfcb952e30
					
				
					 4 changed files with 32 additions and 0 deletions
				
			
		|  | @ -964,6 +964,14 @@ def func2(): | |||
| """ | ||||
|         self._check_error(code, "invalid syntax") | ||||
| 
 | ||||
|     def test_invalid_line_continuation_left_recursive(self): | ||||
|         # Check bpo-42218: SyntaxErrors following left-recursive rules | ||||
|         # (t_primary_raw in this case) need to be tested explicitly | ||||
|         self._check_error("A.\u018a\\ ", | ||||
|                           "unexpected character after line continuation character") | ||||
|         self._check_error("A.\u03bc\\\n", | ||||
|                           "unexpected EOF while parsing") | ||||
| 
 | ||||
| def test_main(): | ||||
|     support.run_unittest(SyntaxTestCase) | ||||
|     from test import test_syntax | ||||
|  |  | |||
|  | @ -0,0 +1,3 @@ | |||
| Fixed a bug in the PEG parser that was causing crashes in debug mode. Now errors are checked | ||||
| in left-recursive rules to avoid cases where such errors do not get handled in time and appear | ||||
| as long-distance crashes in other places. | ||||
|  | @ -3460,6 +3460,8 @@ dotted_name_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = dotted_name_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -9044,6 +9046,8 @@ bitwise_or_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = bitwise_or_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -9158,6 +9162,8 @@ bitwise_xor_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = bitwise_xor_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -9272,6 +9278,8 @@ bitwise_and_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = bitwise_and_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -9386,6 +9394,8 @@ shift_expr_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = shift_expr_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -9539,6 +9549,8 @@ sum_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = sum_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -9698,6 +9710,8 @@ term_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = term_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -10302,6 +10316,8 @@ primary_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = primary_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  | @ -13962,6 +13978,8 @@ t_primary_rule(Parser *p) | |||
|         } | ||||
|         p->mark = _mark; | ||||
|         void *_raw = t_primary_raw(p); | ||||
|         if (p->error_indicator) | ||||
|             return NULL; | ||||
|         if (_raw == NULL || p->mark <= _resmark) | ||||
|             break; | ||||
|         _resmark = p->mark; | ||||
|  |  | |||
|  | @ -496,6 +496,9 @@ def _set_up_rule_memoization(self, node: Rule, result_type: str) -> None: | |||
|                 ) | ||||
|                 self.print("p->mark = _mark;") | ||||
|                 self.print(f"void *_raw = {node.name}_raw(p);") | ||||
|                 self.print("if (p->error_indicator)") | ||||
|                 with self.indent(): | ||||
|                     self.print("return NULL;") | ||||
|                 self.print("if (_raw == NULL || p->mark <= _resmark)") | ||||
|                 with self.indent(): | ||||
|                     self.print("break;") | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lysandros Nikolaou
						Lysandros Nikolaou