mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Fix #9324: Add parameter validation to signal.signal on Windows in order
to prevent crashes.
This commit is contained in:
		
							parent
							
								
									e6fc7401a9
								
							
						
					
					
						commit
						ef9efbd69c
					
				
					 4 changed files with 50 additions and 5 deletions
				
			
		|  | @ -230,6 +230,10 @@ The :mod:`signal` module defines the following functions: | |||
|    see the :ref:`description in the type hierarchy <frame-objects>` or see the | ||||
|    attribute descriptions in the :mod:`inspect` module). | ||||
| 
 | ||||
|    On Windows, :func:`signal` can only be called with :const:`SIGABRT`, | ||||
|    :const:`SIGFPE`, :const:`SIGILL`, :const:`SIGINT`, :const:`SIGSEGV`, or | ||||
|    :const:`SIGTERM`. A :exc:`ValueError` will be raised in any other case. | ||||
| 
 | ||||
| 
 | ||||
| .. _signal-example: | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| import traceback | ||||
| import sys, os, time, errno | ||||
| 
 | ||||
| if sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos': | ||||
| if sys.platform == 'os2' or sys.platform == 'riscos': | ||||
|     raise unittest.SkipTest("Can't test signal on %s" % \ | ||||
|                                    sys.platform) | ||||
| 
 | ||||
|  | @ -37,6 +37,7 @@ def ignoring_eintr(__func, *args, **kwargs): | |||
|         return None | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | ||||
| class InterProcessSignalTests(unittest.TestCase): | ||||
|     MAX_DURATION = 20   # Entire test should last at most 20 sec. | ||||
| 
 | ||||
|  | @ -186,6 +187,7 @@ def test_main(self): | |||
|                           self.MAX_DURATION) | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | ||||
| class BasicSignalTests(unittest.TestCase): | ||||
|     def trivial_signal_handler(self, *args): | ||||
|         pass | ||||
|  | @ -208,6 +210,23 @@ def test_getsignal(self): | |||
|         self.assertEquals(signal.getsignal(signal.SIGHUP), hup) | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipUnless(sys.platform == "win32", "Windows specific") | ||||
| class WindowsSignalTests(unittest.TestCase): | ||||
|     def test_issue9324(self): | ||||
|         handler = lambda x, y: None | ||||
|         signal.signal(signal.SIGABRT, handler) | ||||
|         signal.signal(signal.SIGFPE, handler) | ||||
|         signal.signal(signal.SIGILL, handler) | ||||
|         signal.signal(signal.SIGINT, handler) | ||||
|         signal.signal(signal.SIGSEGV, handler) | ||||
|         signal.signal(signal.SIGTERM, handler) | ||||
| 
 | ||||
|         with self.assertRaises(ValueError): | ||||
|             signal.signal(-1, handler) | ||||
|             sinal.signal(7, handler) | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | ||||
| class WakeupSignalTests(unittest.TestCase): | ||||
|     TIMEOUT_FULL = 10 | ||||
|     TIMEOUT_HALF = 5 | ||||
|  | @ -253,14 +272,15 @@ def tearDown(self): | |||
|         os.close(self.write) | ||||
|         signal.signal(signal.SIGALRM, self.alrm) | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | ||||
| class SiginterruptTest(unittest.TestCase): | ||||
|     signum = signal.SIGUSR1 | ||||
| 
 | ||||
|     def setUp(self): | ||||
|         """Install a no-op signal handler that can be set to allow | ||||
|         interrupts or not, and arrange for the original signal handler to be | ||||
|         re-installed when the test is finished. | ||||
|         """ | ||||
|         self.signum = signal.SIGUSR1 | ||||
|         oldhandler = signal.signal(self.signum, lambda x,y: None) | ||||
|         self.addCleanup(signal.signal, self.signum, oldhandler) | ||||
| 
 | ||||
|  | @ -354,7 +374,7 @@ def test_siginterrupt_off(self): | |||
|         self.assertFalse(i) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") | ||||
| class ItimerTest(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         self.hndl_called = False | ||||
|  | @ -463,6 +483,9 @@ def test_itimer_prof(self): | |||
|         self.assertEqual(self.hndl_called, True) | ||||
| 
 | ||||
| def test_main(): | ||||
|     if sys.platform == "win32": | ||||
|         support.run_unittest(WindowsSignalTests) | ||||
|     else: | ||||
|         support.run_unittest(BasicSignalTests, InterProcessSignalTests, | ||||
|             WakeupSignalTests, SiginterruptTest, ItimerTest) | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,6 +24,9 @@ Core and Builtins | |||
| Extensions | ||||
| ---------- | ||||
| 
 | ||||
| - Issue #9324: Add parameter validation to signal.signal on Windows in order | ||||
|   to prevent crashes. | ||||
| 
 | ||||
| - Issue #9526: Remove some outdated (int) casts that were preventing | ||||
|   the array module from working correctly with arrays of more than | ||||
|   2**31 elements. | ||||
|  |  | |||
|  | @ -255,8 +255,23 @@ signal_signal(PyObject *self, PyObject *args) | |||
|     int sig_num; | ||||
|     PyObject *old_handler; | ||||
|     void (*func)(int); | ||||
| #ifdef MS_WINDOWS | ||||
|     int cur_sig, num_valid_sigs = 6; | ||||
|     static int valid_sigs[] = {SIGABRT, SIGFPE, SIGILL, SIGINT, | ||||
|                                SIGSEGV, SIGTERM}; | ||||
|     BOOL valid_sig = FALSE; | ||||
| #endif | ||||
|     if (!PyArg_ParseTuple(args, "iO:signal", &sig_num, &obj)) | ||||
|         return NULL; | ||||
| #ifdef MS_WINDOWS | ||||
|     /* Validate that sig_num is one of the allowable signals */ | ||||
|     for (cur_sig = 0; cur_sig < num_valid_sigs; cur_sig++) | ||||
|         valid_sig |= (sig_num == valid_sigs[cur_sig]); | ||||
|     if (!valid_sig) { | ||||
|         PyErr_SetString(PyExc_ValueError, "signal number out of range"); | ||||
|         return NULL; | ||||
|     } | ||||
| #endif | ||||
| #ifdef WITH_THREAD | ||||
|     if (PyThread_get_thread_ident() != main_thread) { | ||||
|         PyErr_SetString(PyExc_ValueError, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brian Curtin
						Brian Curtin