#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.
|
- 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?
|
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",
|
if (!PyArg_ParseTuple(args, "Oi:raise_exception",
|
||||||
&exc, &num_args))
|
&exc, &num_args))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (!PyExceptionClass_Check(exc)) {
|
||||||
|
PyErr_Format(PyExc_TypeError, "an exception class is required");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
exc_args = PyTuple_New(num_args);
|
exc_args = PyTuple_New(num_args);
|
||||||
if (exc_args == NULL)
|
if (exc_args == NULL)
|
||||||
|
@ -628,14 +632,17 @@ raise_exception(PyObject *self, PyObject *args)
|
||||||
*/
|
*/
|
||||||
static PyThread_type_lock thread_done = NULL;
|
static PyThread_type_lock thread_done = NULL;
|
||||||
|
|
||||||
static void
|
static int
|
||||||
_make_call(void *callable)
|
_make_call(void *callable)
|
||||||
{
|
{
|
||||||
PyObject *rc;
|
PyObject *rc;
|
||||||
|
int success;
|
||||||
PyGILState_STATE s = PyGILState_Ensure();
|
PyGILState_STATE s = PyGILState_Ensure();
|
||||||
rc = PyObject_CallFunction((PyObject *)callable, "");
|
rc = PyObject_CallFunction((PyObject *)callable, "");
|
||||||
|
success = (rc != NULL);
|
||||||
Py_XDECREF(rc);
|
Py_XDECREF(rc);
|
||||||
PyGILState_Release(s);
|
PyGILState_Release(s);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same thing, but releases `thread_done` when it returns. This variant
|
/* Same thing, but releases `thread_done` when it returns. This variant
|
||||||
|
@ -652,10 +659,17 @@ static PyObject *
|
||||||
test_thread_state(PyObject *self, PyObject *args)
|
test_thread_state(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *fn;
|
PyObject *fn;
|
||||||
|
int success = 1;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O:test_thread_state", &fn))
|
if (!PyArg_ParseTuple(args, "O:test_thread_state", &fn))
|
||||||
return NULL;
|
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 */
|
/* Ensure Python is set up for threading */
|
||||||
PyEval_InitThreads();
|
PyEval_InitThreads();
|
||||||
thread_done = PyThread_allocate_lock();
|
thread_done = PyThread_allocate_lock();
|
||||||
|
@ -666,10 +680,10 @@ test_thread_state(PyObject *self, PyObject *args)
|
||||||
/* Start a new thread with our callback. */
|
/* Start a new thread with our callback. */
|
||||||
PyThread_start_new_thread(_make_call_from_thread, fn);
|
PyThread_start_new_thread(_make_call_from_thread, fn);
|
||||||
/* Make the callback with the thread lock held by this thread */
|
/* 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 */
|
/* Do it all again, but this time with the thread-lock released */
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
_make_call(fn);
|
success &= _make_call(fn);
|
||||||
PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */
|
PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
@ -679,7 +693,7 @@ test_thread_state(PyObject *self, PyObject *args)
|
||||||
*/
|
*/
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
PyThread_start_new_thread(_make_call_from_thread, fn);
|
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 */
|
PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
@ -687,6 +701,8 @@ test_thread_state(PyObject *self, PyObject *args)
|
||||||
PyThread_release_lock(thread_done);
|
PyThread_release_lock(thread_done);
|
||||||
|
|
||||||
PyThread_free_lock(thread_done);
|
PyThread_free_lock(thread_done);
|
||||||
|
if (!success)
|
||||||
|
return NULL;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue