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") |         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(): | def test_main(): | ||||||
|     support.run_unittest(SyntaxTestCase) |     support.run_unittest(SyntaxTestCase) | ||||||
|     from test import test_syntax |     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; |         p->mark = _mark; | ||||||
|         void *_raw = dotted_name_raw(p); |         void *_raw = dotted_name_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -9044,6 +9046,8 @@ bitwise_or_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = bitwise_or_raw(p); |         void *_raw = bitwise_or_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -9158,6 +9162,8 @@ bitwise_xor_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = bitwise_xor_raw(p); |         void *_raw = bitwise_xor_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -9272,6 +9278,8 @@ bitwise_and_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = bitwise_and_raw(p); |         void *_raw = bitwise_and_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -9386,6 +9394,8 @@ shift_expr_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = shift_expr_raw(p); |         void *_raw = shift_expr_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -9539,6 +9549,8 @@ sum_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = sum_raw(p); |         void *_raw = sum_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -9698,6 +9710,8 @@ term_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = term_raw(p); |         void *_raw = term_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -10302,6 +10316,8 @@ primary_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = primary_raw(p); |         void *_raw = primary_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _resmark = p->mark; | ||||||
|  | @ -13962,6 +13978,8 @@ t_primary_rule(Parser *p) | ||||||
|         } |         } | ||||||
|         p->mark = _mark; |         p->mark = _mark; | ||||||
|         void *_raw = t_primary_raw(p); |         void *_raw = t_primary_raw(p); | ||||||
|  |         if (p->error_indicator) | ||||||
|  |             return NULL; | ||||||
|         if (_raw == NULL || p->mark <= _resmark) |         if (_raw == NULL || p->mark <= _resmark) | ||||||
|             break; |             break; | ||||||
|         _resmark = p->mark; |         _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("p->mark = _mark;") | ||||||
|                 self.print(f"void *_raw = {node.name}_raw(p);") |                 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)") |                 self.print("if (_raw == NULL || p->mark <= _resmark)") | ||||||
|                 with self.indent(): |                 with self.indent(): | ||||||
|                     self.print("break;") |                     self.print("break;") | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lysandros Nikolaou
						Lysandros Nikolaou