diff options
author | Steve Dower <steve.dower@microsoft.com> | 2017-02-04 15:05:40 -0800 |
---|---|---|
committer | Steve Dower <steve.dower@microsoft.com> | 2017-02-04 15:05:40 -0800 |
commit | b2fa705fd3887c326e811c418469c784353027f4 (patch) | |
tree | b3428f73de91453edbfd4df1a5d4a212d182eb44 /Modules/_testcapimodule.c | |
parent | 134e58fd3aaa2e91390041e143f3f0a21a60142b (diff) | |
parent | b53654b6dbfce8318a7d4d1cdaddca7a7fec194b (diff) | |
download | cpython-b2fa705fd3887c326e811c418469c784353027f4.tar.gz |
Issue #29392: Prevent crash when passing invalid arguments into msvcrt module.
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r-- | Modules/_testcapimodule.c | 314 |
1 files changed, 241 insertions, 73 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 060a92da4b..f09205f63c 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -60,9 +60,7 @@ test_config(PyObject *self) CHECK_SIZEOF(SIZEOF_LONG, long); CHECK_SIZEOF(SIZEOF_VOID_P, void*); CHECK_SIZEOF(SIZEOF_TIME_T, time_t); -#ifdef HAVE_LONG_LONG - CHECK_SIZEOF(SIZEOF_LONG_LONG, PY_LONG_LONG); -#endif + CHECK_SIZEOF(SIZEOF_LONG_LONG, long long); #undef CHECK_SIZEOF @@ -100,22 +98,14 @@ test_sizeof_c_types(PyObject *self) CHECK_SIGNNESS(Py_UCS1, 0); CHECK_SIGNNESS(Py_UCS2, 0); CHECK_SIGNNESS(Py_UCS4, 0); -#ifdef HAVE_INT32_T - CHECK_SIZEOF(PY_INT32_T, 4); - CHECK_SIGNNESS(PY_INT32_T, 1); -#endif -#ifdef HAVE_UINT32_T - CHECK_SIZEOF(PY_UINT32_T, 4); - CHECK_SIGNNESS(PY_UINT32_T, 0); -#endif -#ifdef HAVE_INT64_T - CHECK_SIZEOF(PY_INT64_T, 8); - CHECK_SIGNNESS(PY_INT64_T, 1); -#endif -#ifdef HAVE_UINT64_T - CHECK_SIZEOF(PY_UINT64_T, 8); - CHECK_SIGNNESS(PY_UINT64_T, 0); -#endif + CHECK_SIZEOF(int32_t, 4); + CHECK_SIGNNESS(int32_t, 1); + CHECK_SIZEOF(uint32_t, 4); + CHECK_SIGNNESS(uint32_t, 0); + CHECK_SIZEOF(int64_t, 8); + CHECK_SIGNNESS(int64_t, 1); + CHECK_SIZEOF(uint64_t, 8); + CHECK_SIGNNESS(uint64_t, 0); /* pointer/size types */ CHECK_SIZEOF(size_t, sizeof(void *)); @@ -123,10 +113,10 @@ test_sizeof_c_types(PyObject *self) CHECK_SIZEOF(Py_ssize_t, sizeof(void *)); CHECK_SIGNNESS(Py_ssize_t, 1); - CHECK_SIZEOF(Py_uintptr_t, sizeof(void *)); - CHECK_SIGNNESS(Py_uintptr_t, 0); - CHECK_SIZEOF(Py_intptr_t, sizeof(void *)); - CHECK_SIGNNESS(Py_intptr_t, 1); + CHECK_SIZEOF(uintptr_t, sizeof(void *)); + CHECK_SIGNNESS(uintptr_t, 0); + CHECK_SIZEOF(intptr_t, sizeof(void *)); + CHECK_SIGNNESS(intptr_t, 1); Py_INCREF(Py_None); return Py_None; @@ -248,13 +238,37 @@ test_dict_iteration(PyObject* self) return Py_None; } +static PyObject* +dict_getitem_knownhash(PyObject *self, PyObject *args) +{ + PyObject *mp, *key, *result; + Py_ssize_t hash; + + if (!PyArg_ParseTuple(args, "OOn:dict_getitem_knownhash", + &mp, &key, &hash)) { + return NULL; + } + + result = _PyDict_GetItem_KnownHash(mp, key, (Py_hash_t)hash); + if (result == NULL && !PyErr_Occurred()) { + _PyErr_SetKeyError(key); + return NULL; + } + + Py_XINCREF(result); + return result; +} static PyObject* dict_hassplittable(PyObject *self, PyObject *arg) { - if (!PyArg_Parse(arg, "O!:dict_hassplittable", &PyDict_Type, &arg)) { + if (!PyDict_Check(arg)) { + PyErr_Format(PyExc_TypeError, + "dict_hassplittable() argument must be dict, not '%s'", + arg->ob_type->tp_name); return NULL; } + return PyBool_FromLong(_PyDict_HasSplitTable((PyDictObject*)arg)); } @@ -366,12 +380,12 @@ test_lazy_hash_inheritance(PyObject* self) } -/* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG) +/* Tests of PyLong_{As, From}{Unsigned,}Long(), and PyLong_{As, From}{Unsigned,}LongLong(). Note that the meat of the test is contained in testcapi_long.h. This is revolting, but delicate code duplication is worse: "almost - exactly the same" code is needed to test PY_LONG_LONG, but the ubiquitous + exactly the same" code is needed to test long long, but the ubiquitous dependence on type names makes it impossible to use a parameterized function. A giant macro would be even worse than this. A C++ template would be perfect. @@ -411,8 +425,6 @@ test_long_api(PyObject* self) #undef F_U_TO_PY #undef F_PY_TO_U -#ifdef HAVE_LONG_LONG - static PyObject * raise_test_longlong_error(const char* msg) { @@ -420,7 +432,7 @@ raise_test_longlong_error(const char* msg) } #define TESTNAME test_longlong_api_inner -#define TYPENAME PY_LONG_LONG +#define TYPENAME long long #define F_S_TO_PY PyLong_FromLongLong #define F_PY_TO_S PyLong_AsLongLong #define F_U_TO_PY PyLong_FromUnsignedLongLong @@ -607,7 +619,7 @@ test_long_and_overflow(PyObject *self) } /* Test the PyLong_AsLongLongAndOverflow API. General conversion to - PY_LONG_LONG is tested by test_long_api_inner. This test will + long long is tested by test_long_api_inner. This test will concentrate on proper handling of overflow. */ @@ -615,7 +627,7 @@ static PyObject * test_long_long_and_overflow(PyObject *self) { PyObject *num, *one, *temp; - PY_LONG_LONG value; + long long value; int overflow; /* Test that overflow is set properly for a large value. */ @@ -833,7 +845,7 @@ test_long_as_double(PyObject *self) return Py_None; } -/* Test the L code for PyArg_ParseTuple. This should deliver a PY_LONG_LONG +/* Test the L code for PyArg_ParseTuple. This should deliver a long long for both long and int arguments. The test may leak a little memory if it fails. */ @@ -841,7 +853,7 @@ static PyObject * test_L_code(PyObject *self) { PyObject *tuple, *num; - PY_LONG_LONG value; + long long value; tuple = PyTuple_New(1); if (tuple == NULL) @@ -879,8 +891,6 @@ test_L_code(PyObject *self) return Py_None; } -#endif /* ifdef HAVE_LONG_LONG */ - static PyObject * return_none(void *unused) { @@ -1010,7 +1020,7 @@ static PyObject * getargs_keywords(PyObject *self, PyObject *args, PyObject *kwargs) { static char *keywords[] = {"arg1","arg2","arg3","arg4","arg5", NULL}; - static char *fmt="(ii)i|(i(ii))(iii)i"; + static const char fmt[] = "(ii)i|(i(ii))(iii)i"; int int_args[10]={-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, fmt, keywords, @@ -1037,6 +1047,21 @@ getargs_keyword_only(PyObject *self, PyObject *args, PyObject *kwargs) return Py_BuildValue("iii", required, optional, keyword_only); } +/* test PyArg_ParseTupleAndKeywords positional-only arguments */ +static PyObject * +getargs_positional_only_and_keywords(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *keywords[] = {"", "", "keyword", NULL}; + int required = -1; + int optional = -1; + int keyword = -1; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii", keywords, + &required, &optional, &keyword)) + return NULL; + return Py_BuildValue("iii", required, optional, keyword); +} + /* Functions to call PyArg_ParseTuple with integer format codes, and return the result. */ @@ -1130,11 +1155,10 @@ getargs_p(PyObject *self, PyObject *args) return PyLong_FromLong(value); } -#ifdef HAVE_LONG_LONG static PyObject * getargs_L(PyObject *self, PyObject *args) { - PY_LONG_LONG value; + long long value; if (!PyArg_ParseTuple(args, "L", &value)) return NULL; return PyLong_FromLongLong(value); @@ -1143,12 +1167,11 @@ getargs_L(PyObject *self, PyObject *args) static PyObject * getargs_K(PyObject *self, PyObject *args) { - unsigned PY_LONG_LONG value; + unsigned long long value; if (!PyArg_ParseTuple(args, "K", &value)) return NULL; return PyLong_FromUnsignedLongLong(value); } -#endif /* This function not only tests the 'k' getargs code, but also the PyLong_AsUnsignedLongMask() and PyLong_AsUnsignedLongMask() functions. */ @@ -1170,7 +1193,7 @@ test_k_code(PyObject *self) value = PyLong_AsUnsignedLongMask(num); if (value != ULONG_MAX) return raiseTestError("test_k_code", - "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF"); + "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF"); PyTuple_SET_ITEM(tuple, 0, num); @@ -1189,7 +1212,7 @@ test_k_code(PyObject *self) value = PyLong_AsUnsignedLongMask(num); if (value != (unsigned long)-0x42) return raiseTestError("test_k_code", - "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF"); + "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF"); PyTuple_SET_ITEM(tuple, 0, num); @@ -2202,7 +2225,7 @@ _make_call(void *callable) PyObject *rc; int success; PyGILState_STATE s = PyGILState_Ensure(); - rc = PyObject_CallFunction((PyObject *)callable, ""); + rc = _PyObject_CallNoArg((PyObject *)callable); success = (rc != NULL); Py_XDECREF(rc); PyGILState_Release(s); @@ -2336,10 +2359,8 @@ test_string_from_format(PyObject *self, PyObject *args) CHECK_1_FORMAT("%zu", size_t); /* "%lld" and "%llu" support added in Python 2.7. */ -#ifdef HAVE_LONG_LONG - CHECK_1_FORMAT("%llu", unsigned PY_LONG_LONG); - CHECK_1_FORMAT("%lld", PY_LONG_LONG); -#endif + CHECK_1_FORMAT("%llu", unsigned long long); + CHECK_1_FORMAT("%lld", long long); Py_RETURN_NONE; @@ -2384,7 +2405,7 @@ test_string_to_double(PyObject *self) { result = PyOS_string_to_double(STR, NULL, NULL); \ if (result == -1.0 && PyErr_Occurred()) \ return NULL; \ - if (result != expected) { \ + if (result != (double)expected) { \ msg = "conversion of " STR " to float failed"; \ goto fail; \ } @@ -2976,7 +2997,9 @@ run_in_subinterp(PyObject *self, PyObject *args) static int check_time_rounding(int round) { - if (round != _PyTime_ROUND_FLOOR && round != _PyTime_ROUND_CEILING) { + if (round != _PyTime_ROUND_FLOOR + && round != _PyTime_ROUND_CEILING + && round != _PyTime_ROUND_HALF_EVEN) { PyErr_SetString(PyExc_ValueError, "invalid rounding"); return -1; } @@ -3471,7 +3494,7 @@ temporary_c_thread(void *data) /* Allocate a Python thread state for this thread */ state = PyGILState_Ensure(); - res = PyObject_CallFunction(test_c_thread->callback, "", NULL); + res = _PyObject_CallNoArg(test_c_thread->callback); Py_CLEAR(test_c_thread->callback); if (res == NULL) { @@ -3761,7 +3784,7 @@ test_pytime_fromsecondsobject(PyObject *self, PyObject *args) static PyObject * test_pytime_assecondsdouble(PyObject *self, PyObject *args) { - PY_LONG_LONG ns; + long long ns; _PyTime_t ts; double d; @@ -3775,7 +3798,7 @@ test_pytime_assecondsdouble(PyObject *self, PyObject *args) static PyObject * test_PyTime_AsTimeval(PyObject *self, PyObject *args) { - PY_LONG_LONG ns; + long long ns; int round; _PyTime_t t; struct timeval tv; @@ -3789,7 +3812,7 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args) if (_PyTime_AsTimeval(t, &tv, round) < 0) return NULL; - seconds = PyLong_FromLong((PY_LONG_LONG)tv.tv_sec); + seconds = PyLong_FromLong((long long)tv.tv_sec); if (seconds == NULL) return NULL; return Py_BuildValue("Nl", seconds, tv.tv_usec); @@ -3799,7 +3822,7 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args) static PyObject * test_PyTime_AsTimespec(PyObject *self, PyObject *args) { - PY_LONG_LONG ns; + long long ns; _PyTime_t t; struct timespec ts; @@ -3815,7 +3838,7 @@ test_PyTime_AsTimespec(PyObject *self, PyObject *args) static PyObject * test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) { - PY_LONG_LONG ns; + long long ns; int round; _PyTime_t t, ms; @@ -3833,7 +3856,7 @@ test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) static PyObject * test_PyTime_AsMicroseconds(PyObject *self, PyObject *args) { - PY_LONG_LONG ns; + long long ns; int round; _PyTime_t t, ms; @@ -3857,6 +3880,152 @@ get_recursion_depth(PyObject *self, PyObject *args) return PyLong_FromLong(tstate->recursion_depth - 1); } +static PyObject* +pymem_buffer_overflow(PyObject *self, PyObject *args) +{ + char *buffer; + + /* Deliberate buffer overflow to check that PyMem_Free() detects + the overflow when debug hooks are installed. */ + buffer = PyMem_Malloc(16); + buffer[16] = 'x'; + PyMem_Free(buffer); + + Py_RETURN_NONE; +} + +static PyObject* +pymem_api_misuse(PyObject *self, PyObject *args) +{ + char *buffer; + + /* Deliberate misusage of Python allocators: + allococate with PyMem but release with PyMem_Raw. */ + buffer = PyMem_Malloc(16); + PyMem_RawFree(buffer); + + Py_RETURN_NONE; +} + +static PyObject* +pymem_malloc_without_gil(PyObject *self, PyObject *args) +{ + char *buffer; + + /* Deliberate bug to test debug hooks on Python memory allocators: + call PyMem_Malloc() without holding the GIL */ + Py_BEGIN_ALLOW_THREADS + buffer = PyMem_Malloc(10); + Py_END_ALLOW_THREADS + + PyMem_Free(buffer); + + Py_RETURN_NONE; +} + +static PyObject* +pyobject_malloc_without_gil(PyObject *self, PyObject *args) +{ + char *buffer; + + /* Deliberate bug to test debug hooks on Python memory allocators: + call PyObject_Malloc() without holding the GIL */ + Py_BEGIN_ALLOW_THREADS + buffer = PyObject_Malloc(10); + Py_END_ALLOW_THREADS + + PyObject_Free(buffer); + + Py_RETURN_NONE; +} + +static PyObject * +tracemalloc_track(PyObject *self, PyObject *args) +{ + unsigned int domain; + PyObject *ptr_obj; + void *ptr; + Py_ssize_t size; + int release_gil = 0; + int res; + + if (!PyArg_ParseTuple(args, "IOn|i", &domain, &ptr_obj, &size, &release_gil)) + return NULL; + ptr = PyLong_AsVoidPtr(ptr_obj); + if (PyErr_Occurred()) + return NULL; + + if (release_gil) { + Py_BEGIN_ALLOW_THREADS + res = _PyTraceMalloc_Track(domain, (uintptr_t)ptr, size); + Py_END_ALLOW_THREADS + } + else { + res = _PyTraceMalloc_Track(domain, (uintptr_t)ptr, size); + } + + if (res < 0) { + PyErr_SetString(PyExc_RuntimeError, "_PyTraceMalloc_Track error"); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject * +tracemalloc_untrack(PyObject *self, PyObject *args) +{ + unsigned int domain; + PyObject *ptr_obj; + void *ptr; + int res; + + if (!PyArg_ParseTuple(args, "IO", &domain, &ptr_obj)) + return NULL; + ptr = PyLong_AsVoidPtr(ptr_obj); + if (PyErr_Occurred()) + return NULL; + + res = _PyTraceMalloc_Untrack(domain, (uintptr_t)ptr); + if (res < 0) { + PyErr_SetString(PyExc_RuntimeError, "_PyTraceMalloc_Track error"); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject * +tracemalloc_get_traceback(PyObject *self, PyObject *args) +{ + unsigned int domain; + PyObject *ptr_obj; + void *ptr; + + if (!PyArg_ParseTuple(args, "IO", &domain, &ptr_obj)) + return NULL; + ptr = PyLong_AsVoidPtr(ptr_obj); + if (PyErr_Occurred()) + return NULL; + + return _PyTraceMalloc_GetTraceback(domain, (uintptr_t)ptr); +} + +static PyObject * +dict_get_version(PyObject *self, PyObject *args) +{ + PyDictObject *dict; + uint64_t version; + + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict)) + return NULL; + + version = dict->ma_version_tag; + + Py_BUILD_ASSERT(sizeof(unsigned PY_LONG_LONG) >= sizeof(version)); + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)version); +} + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -3867,6 +4036,7 @@ static PyMethodDef TestMethods[] = { {"test_datetime_capi", test_datetime_capi, METH_NOARGS}, {"test_list_api", (PyCFunction)test_list_api, METH_NOARGS}, {"test_dict_iteration", (PyCFunction)test_dict_iteration,METH_NOARGS}, + {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS}, {"dict_hassplittable", dict_hassplittable, METH_O}, {"test_lazy_hash_inheritance", (PyCFunction)test_lazy_hash_inheritance,METH_NOARGS}, {"test_long_api", (PyCFunction)test_long_api, METH_NOARGS}, @@ -3903,6 +4073,9 @@ static PyMethodDef TestMethods[] = { METH_VARARGS|METH_KEYWORDS}, {"getargs_keyword_only", (PyCFunction)getargs_keyword_only, METH_VARARGS|METH_KEYWORDS}, + {"getargs_positional_only_and_keywords", + (PyCFunction)getargs_positional_only_and_keywords, + METH_VARARGS|METH_KEYWORDS}, {"getargs_b", getargs_b, METH_VARARGS}, {"getargs_B", getargs_B, METH_VARARGS}, {"getargs_h", getargs_h, METH_VARARGS}, @@ -3913,14 +4086,12 @@ static PyMethodDef TestMethods[] = { {"getargs_l", getargs_l, METH_VARARGS}, {"getargs_n", getargs_n, METH_VARARGS}, {"getargs_p", getargs_p, METH_VARARGS}, -#ifdef HAVE_LONG_LONG {"getargs_L", getargs_L, METH_VARARGS}, {"getargs_K", getargs_K, METH_VARARGS}, {"test_longlong_api", test_longlong_api, METH_NOARGS}, {"test_long_long_and_overflow", (PyCFunction)test_long_long_and_overflow, METH_NOARGS}, {"test_L_code", (PyCFunction)test_L_code, METH_NOARGS}, -#endif {"getargs_f", getargs_f, METH_VARARGS}, {"getargs_d", getargs_d, METH_VARARGS}, {"getargs_D", getargs_D, METH_VARARGS}, @@ -4051,6 +4222,14 @@ static PyMethodDef TestMethods[] = { {"PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS}, {"PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS}, {"get_recursion_depth", get_recursion_depth, METH_NOARGS}, + {"pymem_buffer_overflow", pymem_buffer_overflow, METH_NOARGS}, + {"pymem_api_misuse", pymem_api_misuse, METH_NOARGS}, + {"pymem_malloc_without_gil", pymem_malloc_without_gil, METH_NOARGS}, + {"pyobject_malloc_without_gil", pyobject_malloc_without_gil, METH_NOARGS}, + {"tracemalloc_track", tracemalloc_track, METH_VARARGS}, + {"tracemalloc_untrack", tracemalloc_untrack, METH_VARARGS}, + {"tracemalloc_get_traceback", tracemalloc_get_traceback, METH_VARARGS}, + {"dict_get_version", dict_get_version, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; @@ -4070,10 +4249,8 @@ typedef struct { float float_member; double double_member; char inplace_member[6]; -#ifdef HAVE_LONG_LONG - PY_LONG_LONG longlong_member; - unsigned PY_LONG_LONG ulonglong_member; -#endif + long long longlong_member; + unsigned long long ulonglong_member; } all_structmembers; typedef struct { @@ -4095,10 +4272,8 @@ static struct PyMemberDef test_members[] = { {"T_FLOAT", T_FLOAT, offsetof(test_structmembers, structmembers.float_member), 0, NULL}, {"T_DOUBLE", T_DOUBLE, offsetof(test_structmembers, structmembers.double_member), 0, NULL}, {"T_STRING_INPLACE", T_STRING_INPLACE, offsetof(test_structmembers, structmembers.inplace_member), 0, NULL}, -#ifdef HAVE_LONG_LONG {"T_LONGLONG", T_LONGLONG, offsetof(test_structmembers, structmembers.longlong_member), 0, NULL}, {"T_ULONGLONG", T_ULONGLONG, offsetof(test_structmembers, structmembers.ulonglong_member), 0, NULL}, -#endif {NULL} }; @@ -4110,15 +4285,9 @@ test_structmembers_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) "T_BOOL", "T_BYTE", "T_UBYTE", "T_SHORT", "T_USHORT", "T_INT", "T_UINT", "T_LONG", "T_ULONG", "T_PYSSIZET", "T_FLOAT", "T_DOUBLE", "T_STRING_INPLACE", -#ifdef HAVE_LONG_LONG "T_LONGLONG", "T_ULONGLONG", -#endif NULL}; - static char *fmt = "|bbBhHiIlknfds#" -#ifdef HAVE_LONG_LONG - "LK" -#endif - ; + static const char fmt[] = "|bbBhHiIlknfds#LK"; test_structmembers *ob; const char *s = NULL; Py_ssize_t string_len = 0; @@ -4140,10 +4309,8 @@ test_structmembers_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) &ob->structmembers.float_member, &ob->structmembers.double_member, &s, &string_len -#ifdef HAVE_LONG_LONG , &ob->structmembers.longlong_member, &ob->structmembers.ulonglong_member -#endif )) { Py_DECREF(ob); return NULL; @@ -4469,6 +4636,7 @@ PyInit__testcapi(void) PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyLong_FromSsize_t(PY_SSIZE_T_MAX)); PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyLong_FromSsize_t(PY_SSIZE_T_MIN)); PyModule_AddObject(m, "SIZEOF_PYGC_HEAD", PyLong_FromSsize_t(sizeof(PyGC_Head))); + PyModule_AddObject(m, "SIZEOF_TIME_T", PyLong_FromSsize_t(sizeof(time_t))); Py_INCREF(&PyInstanceMethod_Type); PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type); |