#3643 add a few more checks to _testcapi to prevent segfaults
Author: Victor Stinner Reviewer: Benjamin Peterson
This commit is contained in:
parent
7161cbfcba
commit
37346b2b9b
|
@ -25,6 +25,12 @@ Library
|
|||
|
||||
- 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?
|
||||
================================
|
||||
|
|
|
@ -600,6 +600,10 @@ raise_exception(PyObject *self, PyObject *args)
|
|||
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 @@ raise_exception(PyObject *self, PyObject *args)
|
|||
*/
|
||||
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 @@ static PyObject *
|
|||
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 @@ test_thread_state(PyObject *self, PyObject *args)
|
|||
/* 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 @@ test_thread_state(PyObject *self, PyObject *args)
|
|||
*/
|
||||
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 @@ test_thread_state(PyObject *self, PyObject *args)
|
|||
PyThread_release_lock(thread_done);
|
||||
|
||||
PyThread_free_lock(thread_done);
|
||||
if (!success)
|
||||
return NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue