summaryrefslogtreecommitdiff
path: root/Modules/_testcapimodule.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2014-12-01 13:10:12 +0200
committerSerhiy Storchaka <storchaka@gmail.com>2014-12-01 13:10:12 +0200
commit9a3a7d1676e3e162e2213ddf62c925e8d9b724af (patch)
treec934e04d1f64ced2268ce81c3618e3f416a3ce74 /Modules/_testcapimodule.c
parentcff8685224e9c1d0024aecfb87a2c120ca3a5542 (diff)
parentab27b2a1ce268e24b44ea0e63ccff6b96e4f710e (diff)
downloadcpython-9a3a7d1676e3e162e2213ddf62c925e8d9b724af.tar.gz
Issue #21032. Fixed socket leak if HTTPConnection.getresponse() fails.
Original patch by Martin Panter.
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r--Modules/_testcapimodule.c223
1 files changed, 215 insertions, 8 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 6c17a4155e..245d4f6316 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -11,6 +11,7 @@
#include <float.h>
#include "structmember.h"
#include "datetime.h"
+#include <signal.h>
#ifdef WITH_THREAD
#include "pythread.h"
@@ -1718,7 +1719,7 @@ test_long_numbits(PyObject *self)
{-0xffffL, 16, -1},
{0xfffffffL, 28, 1},
{-0xfffffffL, 28, -1}};
- int i;
+ size_t i;
for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) {
size_t nbits;
@@ -2652,6 +2653,21 @@ with_tp_del(PyObject *self, PyObject *args)
return obj;
}
+static PyMethodDef ml;
+
+static PyObject *
+create_cfunction(PyObject *self, PyObject *args)
+{
+ return PyCFunction_NewEx(&ml, self, NULL);
+}
+
+static PyMethodDef ml = {
+ "create_cfunction",
+ create_cfunction,
+ METH_NOARGS,
+ NULL
+};
+
static PyObject *
_test_incref(PyObject *ob)
{
@@ -2710,6 +2726,20 @@ test_pymem_alloc0(PyObject *self)
{
void *ptr;
+ ptr = PyMem_RawMalloc(0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyMem_RawMalloc(0) returns NULL");
+ return NULL;
+ }
+ PyMem_RawFree(ptr);
+
+ ptr = PyMem_RawCalloc(0, 0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyMem_RawCalloc(0, 0) returns NULL");
+ return NULL;
+ }
+ PyMem_RawFree(ptr);
+
ptr = PyMem_Malloc(0);
if (ptr == NULL) {
PyErr_SetString(PyExc_RuntimeError, "PyMem_Malloc(0) returns NULL");
@@ -2717,6 +2747,13 @@ test_pymem_alloc0(PyObject *self)
}
PyMem_Free(ptr);
+ ptr = PyMem_Calloc(0, 0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyMem_Calloc(0, 0) returns NULL");
+ return NULL;
+ }
+ PyMem_Free(ptr);
+
ptr = PyObject_Malloc(0);
if (ptr == NULL) {
PyErr_SetString(PyExc_RuntimeError, "PyObject_Malloc(0) returns NULL");
@@ -2724,13 +2761,22 @@ test_pymem_alloc0(PyObject *self)
}
PyObject_Free(ptr);
+ ptr = PyObject_Calloc(0, 0);
+ if (ptr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyObject_Calloc(0, 0) returns NULL");
+ return NULL;
+ }
+ PyObject_Free(ptr);
+
Py_RETURN_NONE;
}
typedef struct {
- PyMemAllocator alloc;
+ PyMemAllocatorEx alloc;
size_t malloc_size;
+ size_t calloc_nelem;
+ size_t calloc_elsize;
void *realloc_ptr;
size_t realloc_new_size;
void *free_ptr;
@@ -2743,6 +2789,14 @@ static void* hook_malloc (void* ctx, size_t size)
return hook->alloc.malloc(hook->alloc.ctx, size);
}
+static void* hook_calloc (void* ctx, size_t nelem, size_t elsize)
+{
+ alloc_hook_t *hook = (alloc_hook_t *)ctx;
+ hook->calloc_nelem = nelem;
+ hook->calloc_elsize = elsize;
+ return hook->alloc.calloc(hook->alloc.ctx, nelem, elsize);
+}
+
static void* hook_realloc (void* ctx, void* ptr, size_t new_size)
{
alloc_hook_t *hook = (alloc_hook_t *)ctx;
@@ -2764,17 +2818,15 @@ test_setallocators(PyMemAllocatorDomain domain)
PyObject *res = NULL;
const char *error_msg;
alloc_hook_t hook;
- PyMemAllocator alloc;
- size_t size, size2;
+ PyMemAllocatorEx alloc;
+ size_t size, size2, nelem, elsize;
void *ptr, *ptr2;
- hook.malloc_size = 0;
- hook.realloc_ptr = NULL;
- hook.realloc_new_size = 0;
- hook.free_ptr = NULL;
+ memset(&hook, 0, sizeof(hook));
alloc.ctx = &hook;
alloc.malloc = &hook_malloc;
+ alloc.calloc = &hook_calloc;
alloc.realloc = &hook_realloc;
alloc.free = &hook_free;
PyMem_GetAllocator(domain, &hook.alloc);
@@ -2831,6 +2883,33 @@ test_setallocators(PyMemAllocatorDomain domain)
goto fail;
}
+ nelem = 2;
+ elsize = 5;
+ switch(domain)
+ {
+ case PYMEM_DOMAIN_RAW: ptr = PyMem_RawCalloc(nelem, elsize); break;
+ case PYMEM_DOMAIN_MEM: ptr = PyMem_Calloc(nelem, elsize); break;
+ case PYMEM_DOMAIN_OBJ: ptr = PyObject_Calloc(nelem, elsize); break;
+ default: ptr = NULL; break;
+ }
+
+ if (ptr == NULL) {
+ error_msg = "calloc failed";
+ goto fail;
+ }
+
+ if (hook.calloc_nelem != nelem || hook.calloc_elsize != elsize) {
+ error_msg = "calloc invalid nelem or elsize";
+ goto fail;
+ }
+
+ switch(domain)
+ {
+ case PYMEM_DOMAIN_RAW: PyMem_RawFree(ptr); break;
+ case PYMEM_DOMAIN_MEM: PyMem_Free(ptr); break;
+ case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr); break;
+ }
+
Py_INCREF(Py_None);
res = Py_None;
goto finally;
@@ -3000,6 +3079,24 @@ exit:
}
#endif /* WITH_THREAD */
+static PyObject*
+test_raise_signal(PyObject* self, PyObject *args)
+{
+ int signum, err;
+
+ if (PyArg_ParseTuple(args, "i:raise_signal", &signum) < 0)
+ return NULL;
+
+ err = raise(signum);
+ if (err)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ if (PyErr_CheckSignals() < 0)
+ return NULL;
+
+ Py_RETURN_NONE;
+}
+
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
@@ -3104,6 +3201,7 @@ static PyMethodDef TestMethods[] = {
{"pytime_object_to_timeval", test_pytime_object_to_timeval, METH_VARARGS},
{"pytime_object_to_timespec", test_pytime_object_to_timespec, METH_VARARGS},
{"with_tp_del", with_tp_del, METH_VARARGS},
+ {"create_cfunction", create_cfunction, METH_NOARGS},
{"test_pymem_alloc0",
(PyCFunction)test_pymem_alloc0, METH_NOARGS},
{"test_pymem_setrawallocators",
@@ -3135,6 +3233,8 @@ static PyMethodDef TestMethods[] = {
{"docstring_with_signature_with_defaults",
(PyCFunction)test_with_docstring, METH_NOARGS,
docstring_with_signature_with_defaults},
+ {"raise_signal",
+ (PyCFunction)test_raise_signal, METH_VARARGS},
#ifdef WITH_THREAD
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O,
PyDoc_STR("set_error_class(error_class) -> None")},
@@ -3298,6 +3398,109 @@ static PyTypeObject test_structmembersType = {
};
+typedef struct {
+ PyObject_HEAD
+} matmulObject;
+
+static PyObject *
+matmulType_matmul(PyObject *self, PyObject *other)
+{
+ return Py_BuildValue("(sOO)", "matmul", self, other);
+}
+
+static PyObject *
+matmulType_imatmul(PyObject *self, PyObject *other)
+{
+ return Py_BuildValue("(sOO)", "imatmul", self, other);
+}
+
+static void
+matmulType_dealloc(PyObject *self)
+{
+ Py_TYPE(self)->tp_free(self);
+}
+
+static PyNumberMethods matmulType_as_number = {
+ 0, /* nb_add */
+ 0, /* nb_subtract */
+ 0, /* nb_multiply */
+ 0, /* nb_remainde r*/
+ 0, /* nb_divmod */
+ 0, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* tp_positive */
+ 0, /* tp_absolute */
+ 0, /* tp_bool */
+ 0, /* nb_invert */
+ 0, /* nb_lshift */
+ 0, /* nb_rshift */
+ 0, /* nb_and */
+ 0, /* nb_xor */
+ 0, /* nb_or */
+ 0, /* nb_int */
+ 0, /* nb_reserved */
+ 0, /* nb_float */
+ 0, /* nb_inplace_add */
+ 0, /* nb_inplace_subtract */
+ 0, /* nb_inplace_multiply */
+ 0, /* nb_inplace_remainder */
+ 0, /* nb_inplace_power */
+ 0, /* nb_inplace_lshift */
+ 0, /* nb_inplace_rshift */
+ 0, /* nb_inplace_and */
+ 0, /* nb_inplace_xor */
+ 0, /* nb_inplace_or */
+ 0, /* nb_floor_divide */
+ 0, /* nb_true_divide */
+ 0, /* nb_inplace_floor_divide */
+ 0, /* nb_inplace_true_divide */
+ 0, /* nb_index */
+ matmulType_matmul, /* nb_matrix_multiply */
+ matmulType_imatmul /* nb_matrix_inplace_multiply */
+};
+
+static PyTypeObject matmulType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "matmulType",
+ sizeof(matmulObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ matmulType_dealloc, /* destructor tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ &matmulType_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ "C level type with matrix operations defined",
+ 0, /* traverseproc tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ PyType_GenericNew, /* tp_new */
+ PyObject_Del, /* tp_free */
+};
+
static struct PyModuleDef _testcapimodule = {
PyModuleDef_HEAD_INIT,
@@ -3327,6 +3530,10 @@ PyInit__testcapi(void)
/* don't use a name starting with "test", since we don't want
test_capi to automatically call this */
PyModule_AddObject(m, "_test_structmembersType", (PyObject *)&test_structmembersType);
+ if (PyType_Ready(&matmulType) < 0)
+ return NULL;
+ Py_INCREF(&matmulType);
+ PyModule_AddObject(m, "matmulType", (PyObject *)&matmulType);
PyModule_AddObject(m, "CHAR_MAX", PyLong_FromLong(CHAR_MAX));
PyModule_AddObject(m, "CHAR_MIN", PyLong_FromLong(CHAR_MIN));