[Python-checkins] r66000 - in python/trunk: Misc/NEWS Modules/_testcapimodule.c

benjamin.peterson python-checkins at python.org
Sat Aug 23 22:27:44 CEST 2008


Author: benjamin.peterson
Date: Sat Aug 23 22:27:43 2008
New Revision: 66000

Log:
#3643 add a few more checks to _testcapi to prevent segfaults

Author: Victor Stinner
Reviewer: Benjamin Peterson


Modified:
   python/trunk/Misc/NEWS
   python/trunk/Modules/_testcapimodule.c

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sat Aug 23 22:27:43 2008
@@ -25,6 +25,12 @@
 
 - Fixed two format strings in the _collections module.
 
+Extension Modules
+-----------------
+
+- Issue #3643: Added a few more checks to _testcapi to prevent segfaults by
+  exploitation of poor argument checking.
+
 
 What's New in Python 2.6 beta 3?
 ================================

Modified: python/trunk/Modules/_testcapimodule.c
==============================================================================
--- python/trunk/Modules/_testcapimodule.c	(original)
+++ python/trunk/Modules/_testcapimodule.c	Sat Aug 23 22:27:43 2008
@@ -600,6 +600,10 @@
 	if (!PyArg_ParseTuple(args, "Oi:raise_exception",
 			      &exc, &num_args))
 		return NULL;
+	if (!PyExceptionClass_Check(exc)) {
+		PyErr_Format(PyExc_TypeError, "an exception class is required");
+		return NULL;
+	}
 
 	exc_args = PyTuple_New(num_args);
 	if (exc_args == NULL)
@@ -628,14 +632,17 @@
  */
 static PyThread_type_lock thread_done = NULL;
 
-static void
+static int
 _make_call(void *callable)
 {
 	PyObject *rc;
+	int success;
 	PyGILState_STATE s = PyGILState_Ensure();
 	rc = PyObject_CallFunction((PyObject *)callable, "");
+	success = (rc != NULL);
 	Py_XDECREF(rc);
 	PyGILState_Release(s);
+	return success;
 }
 
 /* Same thing, but releases `thread_done` when it returns.  This variant
@@ -652,10 +659,17 @@
 test_thread_state(PyObject *self, PyObject *args)
 {
 	PyObject *fn;
+	int success = 1;
 
 	if (!PyArg_ParseTuple(args, "O:test_thread_state", &fn))
 		return NULL;
 
+	if (!PyCallable_Check(fn)) {
+		PyErr_Format(PyExc_TypeError, "'%s' object is not callable",
+			fn->ob_type->tp_name);
+		return NULL;
+	}
+
 	/* Ensure Python is set up for threading */
 	PyEval_InitThreads();
 	thread_done = PyThread_allocate_lock();
@@ -666,10 +680,10 @@
 	/* Start a new thread with our callback. */
 	PyThread_start_new_thread(_make_call_from_thread, fn);
 	/* Make the callback with the thread lock held by this thread */
-	_make_call(fn);
+	success &= _make_call(fn);
 	/* Do it all again, but this time with the thread-lock released */
 	Py_BEGIN_ALLOW_THREADS
-	_make_call(fn);
+	success &= _make_call(fn);
 	PyThread_acquire_lock(thread_done, 1);  /* wait for thread to finish */
 	Py_END_ALLOW_THREADS
 
@@ -679,7 +693,7 @@
 	*/
 	Py_BEGIN_ALLOW_THREADS
 	PyThread_start_new_thread(_make_call_from_thread, fn);
-	_make_call(fn);
+	success &= _make_call(fn);
 	PyThread_acquire_lock(thread_done, 1);  /* wait for thread to finish */
 	Py_END_ALLOW_THREADS
 
@@ -687,6 +701,8 @@
 	PyThread_release_lock(thread_done);
 
 	PyThread_free_lock(thread_done);
+	if (!success)
+		return NULL;
 	Py_RETURN_NONE;
 }
 #endif


More information about the Python-checkins mailing list