mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	[3.13] gh-128049: Fix type confusion bug with the return value of a custom ExceptionGroup split function (GH-128079) (#128139)
gh-128049: Fix type confusion bug with the return value of a custom ExceptionGroup split function (GH-128079)
(cherry picked from commit 3879ca0100)
Co-authored-by: Nico-Posada <102486290+Nico-Posada@users.noreply.github.com>
			
			
This commit is contained in:
		
							parent
							
								
									43586a4804
								
							
						
					
					
						commit
						09d15aa9a8
					
				
					 3 changed files with 67 additions and 2 deletions
				
			
		|  | @ -952,6 +952,49 @@ def derive(self, excs): | ||||||
|         self.assertExceptionIsLike(tes, FalsyEG("eg", [TypeError(1)])) |         self.assertExceptionIsLike(tes, FalsyEG("eg", [TypeError(1)])) | ||||||
|         self.assertExceptionIsLike(ves, FalsyEG("eg", [ValueError(2)])) |         self.assertExceptionIsLike(ves, FalsyEG("eg", [ValueError(2)])) | ||||||
| 
 | 
 | ||||||
|  |     def test_exception_group_subclass_with_bad_split_func(self): | ||||||
|  |         # see gh-128049. | ||||||
|  |         class BadEG1(ExceptionGroup): | ||||||
|  |             def split(self, *args): | ||||||
|  |                 return "NOT A 2-TUPLE!" | ||||||
|  | 
 | ||||||
|  |         class BadEG2(ExceptionGroup): | ||||||
|  |             def split(self, *args): | ||||||
|  |                 return ("NOT A 2-TUPLE!",) | ||||||
|  | 
 | ||||||
|  |         eg_list = [ | ||||||
|  |             (BadEG1("eg", [OSError(123), ValueError(456)]), | ||||||
|  |              r"split must return a tuple, not str"), | ||||||
|  |             (BadEG2("eg", [OSError(123), ValueError(456)]), | ||||||
|  |              r"split must return a 2-tuple, got tuple of size 1") | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  |         for eg_class, msg in eg_list: | ||||||
|  |             with self.assertRaisesRegex(TypeError, msg) as m: | ||||||
|  |                 try: | ||||||
|  |                     raise eg_class | ||||||
|  |                 except* ValueError: | ||||||
|  |                     pass | ||||||
|  |                 except* OSError: | ||||||
|  |                     pass | ||||||
|  | 
 | ||||||
|  |             self.assertExceptionIsLike(m.exception.__context__, eg_class) | ||||||
|  | 
 | ||||||
|  |         # we allow tuples of length > 2 for backwards compatibility | ||||||
|  |         class WeirdEG(ExceptionGroup): | ||||||
|  |             def split(self, *args): | ||||||
|  |                 return super().split(*args) + ("anything", 123456, None) | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             raise WeirdEG("eg", [OSError(123), ValueError(456)]) | ||||||
|  |         except* OSError as e: | ||||||
|  |             oeg = e | ||||||
|  |         except* ValueError as e: | ||||||
|  |             veg = e | ||||||
|  | 
 | ||||||
|  |         self.assertExceptionIsLike(oeg, WeirdEG("eg", [OSError(123)])) | ||||||
|  |         self.assertExceptionIsLike(veg, WeirdEG("eg", [ValueError(456)])) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class TestExceptStarCleanup(ExceptStarTest): | class TestExceptStarCleanup(ExceptStarTest): | ||||||
|     def test_sys_exception_restored(self): |     def test_sys_exception_restored(self): | ||||||
|  |  | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | Fix a bug where :keyword:`except* <except_star>` does not properly check the | ||||||
|  | return value of an :exc:`ExceptionGroup`'s :meth:`~BaseExceptionGroup.split` | ||||||
|  | function, leading to a crash in some cases. Now when :meth:`~BaseExceptionGroup.split` | ||||||
|  | returns an invalid object, :keyword:`except* <except_star>` raises a :exc:`TypeError` | ||||||
|  | with the original raised :exc:`ExceptionGroup` object chained to it. | ||||||
|  | @ -2029,8 +2029,25 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type, | ||||||
|         if (pair == NULL) { |         if (pair == NULL) { | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|         assert(PyTuple_CheckExact(pair)); | 
 | ||||||
|         assert(PyTuple_GET_SIZE(pair) == 2); |         if (!PyTuple_CheckExact(pair)) { | ||||||
|  |             PyErr_Format(PyExc_TypeError, | ||||||
|  |                          "%.200s.split must return a tuple, not %.200s", | ||||||
|  |                          Py_TYPE(exc_value)->tp_name, Py_TYPE(pair)->tp_name); | ||||||
|  |             Py_DECREF(pair); | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // allow tuples of length > 2 for backwards compatibility
 | ||||||
|  |         if (PyTuple_GET_SIZE(pair) < 2) { | ||||||
|  |             PyErr_Format(PyExc_TypeError, | ||||||
|  |                          "%.200s.split must return a 2-tuple, " | ||||||
|  |                          "got tuple of size %zd", | ||||||
|  |                          Py_TYPE(exc_value)->tp_name, PyTuple_GET_SIZE(pair)); | ||||||
|  |             Py_DECREF(pair); | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         *match = Py_NewRef(PyTuple_GET_ITEM(pair, 0)); |         *match = Py_NewRef(PyTuple_GET_ITEM(pair, 0)); | ||||||
|         *rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1)); |         *rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1)); | ||||||
|         Py_DECREF(pair); |         Py_DECREF(pair); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Miss Islington (bot)
						Miss Islington (bot)