/* * C Extension module to test Python interpreter C APIs. * * The 'test_*' functions exported by this module are run as part of the * standard Python regression test, via Lib/test/test_capi.py. */ /* This module tests the public (Include/ and Include/cpython/) C API. The internal C API must not be used here: use _testinternalcapi for that. The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE macro defined, but only the public C API must be tested here. */ #undef Py_BUILD_CORE_MODULE #undef Py_BUILD_CORE_BUILTIN /* Always enable assertions */ #undef NDEBUG #define PY_SSIZE_T_CLEAN #include "Python.h" #include "frameobject.h" // PyFrame_New #include "marshal.h" // PyMarshal_WriteLongToFile #include "structmember.h" // for offsetof(), T_OBJECT #include // FLT_MAX #include #ifndef MS_WINDOWS #include #endif #ifdef HAVE_SYS_WAIT_H #include // W_STOPCODE #endif #ifdef Py_BUILD_CORE # error "_testcapi must test the public Python C API, not CPython internal C API" #endif #ifdef bool # error "The public headers should not include , see bpo-46748" #endif // Several parts of this module are broken out into files in _testcapi/. // Include definitions from there. #include "_testcapi/parts.h" // Forward declarations static struct PyModuleDef _testcapimodule; static PyObject *TestError; /* set to exception object in init */ /* Raise TestError with test_name + ": " + msg, and return NULL. */ static PyObject * raiseTestError(const char* test_name, const char* msg) { PyErr_Format(TestError, "%s: %s", test_name, msg); return NULL; } /* Test #defines from pyconfig.h (particularly the SIZEOF_* defines). The ones derived from autoconf on the UNIX-like OSes can be relied upon (in the absence of sloppy cross-compiling), but the Windows platforms have these hardcoded. Better safe than sorry. */ static PyObject* sizeof_error(const char* fatname, const char* typname, int expected, int got) { PyErr_Format(TestError, "%s #define == %d but sizeof(%s) == %d", fatname, expected, typname, got); return (PyObject*)NULL; } static PyObject* test_config(PyObject *self, PyObject *Py_UNUSED(ignored)) { #define CHECK_SIZEOF(FATNAME, TYPE) \ if (FATNAME != sizeof(TYPE)) \ return sizeof_error(#FATNAME, #TYPE, FATNAME, sizeof(TYPE)) CHECK_SIZEOF(SIZEOF_SHORT, short); CHECK_SIZEOF(SIZEOF_INT, int); CHECK_SIZEOF(SIZEOF_LONG, long); CHECK_SIZEOF(SIZEOF_VOID_P, void*); CHECK_SIZEOF(SIZEOF_TIME_T, time_t); CHECK_SIZEOF(SIZEOF_LONG_LONG, long long); #undef CHECK_SIZEOF Py_RETURN_NONE; } static PyObject* test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored)) { #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wtype-limits" #endif #define CHECK_SIZEOF(TYPE, EXPECTED) \ if (EXPECTED != sizeof(TYPE)) { \ PyErr_Format(TestError, \ "sizeof(%s) = %u instead of %u", \ #TYPE, sizeof(TYPE), EXPECTED); \ return (PyObject*)NULL; \ } #define IS_SIGNED(TYPE) (((TYPE)-1) < (TYPE)0) #define CHECK_SIGNNESS(TYPE, SIGNED) \ if (IS_SIGNED(TYPE) != SIGNED) { \ PyErr_Format(TestError, \ "%s signness is, instead of %i", \ #TYPE, IS_SIGNED(TYPE), SIGNED); \ return (PyObject*)NULL; \ } /* integer types */ CHECK_SIZEOF(Py_UCS1, 1); CHECK_SIZEOF(Py_UCS2, 2); CHECK_SIZEOF(Py_UCS4, 4); CHECK_SIGNNESS(Py_UCS1, 0); CHECK_SIGNNESS(Py_UCS2, 0); CHECK_SIGNNESS(Py_UCS4, 0); 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 *)); CHECK_SIGNNESS(size_t, 0); CHECK_SIZEOF(Py_ssize_t, sizeof(void *)); CHECK_SIGNNESS(Py_ssize_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_RETURN_NONE; #undef IS_SIGNED #undef CHECK_SIGNESS #undef CHECK_SIZEOF #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))) #pragma GCC diagnostic pop #endif } static PyObject* test_gc_control(PyObject *self, PyObject *Py_UNUSED(ignored)) { int orig_enabled = PyGC_IsEnabled(); const char* msg = "ok"; int old_state; old_state = PyGC_Enable(); msg = "Enable(1)"; if (old_state != orig_enabled) { goto failed; } msg = "IsEnabled(1)"; if (!PyGC_IsEnabled()) { goto failed; } old_state = PyGC_Disable(); msg = "disable(2)"; if (!old_state) { goto failed; } msg = "IsEnabled(2)"; if (PyGC_IsEnabled()) { goto failed; } old_state = PyGC_Enable(); msg = "enable(3)"; if (old_state) { goto failed; } msg = "IsEnabled(3)"; if (!PyGC_IsEnabled()) { goto failed; } if (!orig_enabled) { old_state = PyGC_Disable(); msg = "disable(4)"; if (old_state) { goto failed; } msg = "IsEnabled(4)"; if (PyGC_IsEnabled()) { goto failed; } } Py_RETURN_NONE; failed: /* Try to clean up if we can. */ if (orig_enabled) { PyGC_Enable(); } else { PyGC_Disable(); } PyErr_Format(TestError, "GC control failed in %s", msg); return NULL; } static PyObject* test_list_api(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyObject* list; int i; /* SF bug 132008: PyList_Reverse segfaults */ #define NLIST 30 list = PyList_New(NLIST); if (list == (PyObject*)NULL) return (PyObject*)NULL; /* list = range(NLIST) */ for (i = 0; i < NLIST; ++i) { PyObject* anint = PyLong_FromLong(i); if (anint == (PyObject*)NULL) { Py_DECREF(list); return (PyObject*)NULL; } PyList_SET_ITEM(list, i, anint); } /* list.reverse(), via PyList_Reverse() */ i = PyList_Reverse(list); /* should not blow up! */ if (i != 0) { Py_DECREF(list); return (PyObject*)NULL; } /* Check that list == range(29, -1, -1) now */ for (i = 0; i < NLIST; ++i) { PyObject* anint = PyList_GET_ITEM(list, i); if (PyLong_AS_LONG(anint) != NLIST-1-i) { PyErr_SetString(TestError, "test_list_api: reverse screwed up"); Py_DECREF(list); return (PyObject*)NULL; } } Py_DECREF(list); #undef NLIST Py_RETURN_NONE; } static int test_dict_inner(int count) { Py_ssize_t pos = 0, iterations = 0; int i; PyObject *dict = PyDict_New(); PyObject *v, *k; if (dict == NULL) return -1; for (i = 0; i < count; i++) { v = PyLong_FromLong(i); if (v == NULL) { return -1; } if (PyDict_SetItem(dict, v, v) < 0) { Py_DECREF(v); return -1; } Py_DECREF(v); } while (PyDict_Next(dict, &pos, &k, &v)) { PyObject *o; iterations++; i = PyLong_AS_LONG(v) + 1; o = PyLong_FromLong(i); if (o == NULL) return -1; if (PyDict_SetItem(dict, k, o) < 0) { Py_DECREF(o); return -1; } Py_DECREF(o); } Py_DECREF(dict); if (iterations != count) { PyErr_SetString( TestError, "test_dict_iteration: dict iteration went wrong "); return -1; } else { return 0; } } static PyObject* test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored)) { int i; for (i = 0; i < 200; i++) { if (test_dict_inner(i) < 0) { return NULL; } } Py_RETURN_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; } return Py_XNewRef(result); } /* Issue #4701: Check that PyObject_Hash implicitly calls * PyType_Ready if it hasn't already been called */ static PyTypeObject _HashInheritanceTester_Type = { PyVarObject_HEAD_INIT(NULL, 0) "hashinheritancetester", /* Name of this type */ sizeof(PyObject), /* Basic object size */ 0, /* Item size for varobject */ (destructor)PyObject_Del, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ }; static PyObject* pycompilestring(PyObject* self, PyObject *obj) { if (PyBytes_CheckExact(obj) == 0) { PyErr_SetString(PyExc_ValueError, "Argument must be a bytes object"); return NULL; } const char *the_string = PyBytes_AsString(obj); if (the_string == NULL) { return NULL; } return Py_CompileString(the_string, "", Py_file_input); } static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { PyTypeObject *type; PyObject *obj; Py_hash_t hash; type = &_HashInheritanceTester_Type; if (type->tp_dict != NULL) /* The type has already been initialized. This probably means -R is being used. */ Py_RETURN_NONE; obj = PyObject_New(PyObject, type); if (obj == NULL) { PyErr_Clear(); PyErr_SetString( TestError, "test_lazy_hash_inheritance: failed to create object"); return NULL; } if (type->tp_dict != NULL) { PyErr_SetString( TestError, "test_lazy_hash_inheritance: type initialised too soon"); Py_DECREF(obj); return NULL; } hash = PyObject_Hash(obj); if ((hash == -1) && PyErr_Occurred()) { PyErr_Clear(); PyErr_SetString( TestError, "test_lazy_hash_inheritance: could not hash object"); Py_DECREF(obj); return NULL; } if (type->tp_dict == NULL) { PyErr_SetString( TestError, "test_lazy_hash_inheritance: type not initialised by hash()"); Py_DECREF(obj); return NULL; } if (type->tp_hash != PyType_Type.tp_hash) { PyErr_SetString( TestError, "test_lazy_hash_inheritance: unexpected hash function"); Py_DECREF(obj); return NULL; } Py_DECREF(obj); Py_RETURN_NONE; } static PyObject * return_none(void *unused) { Py_RETURN_NONE; } static PyObject * raise_error(void *unused) { PyErr_SetNone(PyExc_ValueError); return NULL; } static int test_buildvalue_N_error(const char *fmt) { PyObject *arg, *res; arg = PyList_New(0); if (arg == NULL) { return -1; } Py_INCREF(arg); res = Py_BuildValue(fmt, return_none, NULL, arg); if (res == NULL) { return -1; } Py_DECREF(res); if (Py_REFCNT(arg) != 1) { PyErr_Format(TestError, "test_buildvalue_N: " "arg was not decrefed in successful " "Py_BuildValue(\"%s\")", fmt); return -1; } Py_INCREF(arg); res = Py_BuildValue(fmt, raise_error, NULL, arg); if (res != NULL || !PyErr_Occurred()) { PyErr_Format(TestError, "test_buildvalue_N: " "Py_BuildValue(\"%s\") didn't complain", fmt); return -1; } PyErr_Clear(); if (Py_REFCNT(arg) != 1) { PyErr_Format(TestError, "test_buildvalue_N: " "arg was not decrefed in failed " "Py_BuildValue(\"%s\")", fmt); return -1; } Py_DECREF(arg); return 0; } static PyObject * test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyObject *arg, *res; arg = PyList_New(0); if (arg == NULL) { return NULL; } Py_INCREF(arg); res = Py_BuildValue("N", arg); if (res == NULL) { return NULL; } if (res != arg) { return raiseTestError("test_buildvalue_N", "Py_BuildValue(\"N\") returned wrong result"); } if (Py_REFCNT(arg) != 2) { return raiseTestError("test_buildvalue_N", "arg was not decrefed in Py_BuildValue(\"N\")"); } Py_DECREF(res); Py_DECREF(arg); if (test_buildvalue_N_error("O&N") < 0) return NULL; if (test_buildvalue_N_error("(O&N)") < 0) return NULL; if (test_buildvalue_N_error("[O&N]") < 0) return NULL; if (test_buildvalue_N_error("{O&N}") < 0) return NULL; if (test_buildvalue_N_error("{()O&(())N}") < 0) return NULL; Py_RETURN_NONE; } static PyObject * test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) { newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new); if (PyLong_Type.tp_new != tp_new) { PyErr_SetString(PyExc_AssertionError, "mismatch: tp_new of long"); return NULL; } reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr); if (PyLong_Type.tp_repr != tp_repr) { PyErr_SetString(PyExc_AssertionError, "mismatch: tp_repr of long"); return NULL; } ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_tp_call); if (tp_call != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: tp_call of long"); return NULL; } binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_nb_add); if (PyLong_Type.tp_as_number->nb_add != nb_add) { PyErr_SetString(PyExc_AssertionError, "mismatch: nb_add of long"); return NULL; } lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_mp_length); if (mp_length != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: mp_length of long"); return NULL; } void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1); if (over_value != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: max+1 of long"); return NULL; } tp_new = PyType_GetSlot(&PyLong_Type, 0); if (tp_new != NULL) { PyErr_SetString(PyExc_AssertionError, "mismatch: slot 0 of long"); return NULL; } if (PyErr_ExceptionMatches(PyExc_SystemError)) { // This is the right exception PyErr_Clear(); } else { return NULL; } Py_RETURN_NONE; } static PyType_Slot HeapTypeNameType_slots[] = { {0}, }; static PyType_Spec HeapTypeNameType_Spec = { .name = "_testcapi.HeapTypeNameType", .basicsize = sizeof(PyObject), .flags = Py_TPFLAGS_DEFAULT, .slots = HeapTypeNameType_slots, }; static PyObject * test_get_type_name(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyObject *tp_name = PyType_GetName(&PyLong_Type); assert(strcmp(PyUnicode_AsUTF8(tp_name), "int") == 0); Py_DECREF(tp_name); tp_name = PyType_GetName(&PyModule_Type); assert(strcmp(PyUnicode_AsUTF8(tp_name), "module") == 0); Py_DECREF(tp_name); PyObject *HeapTypeNameType = PyType_FromSpec(&HeapTypeNameType_Spec); if (HeapTypeNameType == NULL) { Py_RETURN_NONE; } tp_name = PyType_GetName((PyTypeObject *)HeapTypeNameType); assert(strcmp(PyUnicode_AsUTF8(tp_name), "HeapTypeNameType") == 0); Py_DECREF(tp_name); PyObject *name = PyUnicode_FromString("test_name"); if (name == NULL) { goto done; } if (PyObject_SetAttrString(HeapTypeNameType, "__name__", name) < 0) { Py_DECREF(name); goto done; } tp_name = PyType_GetName((PyTypeObject *)HeapTypeNameType); assert(strcmp(PyUnicode_AsUTF8(tp_name), "test_name") == 0); Py_DECREF(name); Py_DECREF(tp_name); done: Py_DECREF(HeapTypeNameType); Py_RETURN_NONE; } static PyObject * test_get_type_qualname(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyObject *tp_qualname = PyType_GetQualName(&PyLong_Type); assert(strcmp(PyUnicode_AsUTF8(tp_qualname), "int") == 0); Py_DECREF(tp_qualname); tp_qualname = PyType_GetQualName(&PyODict_Type); assert(strcmp(PyUnicode_AsUTF8(tp_qualname), "OrderedDict") == 0); Py_DECREF(tp_qualname); PyObject *HeapTypeNameType = PyType_FromSpec(&HeapTypeNameType_Spec); if (HeapTypeNameType == NULL) { Py_RETURN_NONE; } tp_qualname = PyType_GetQualName((PyTypeObject *)HeapTypeNameType); assert(strcmp(PyUnicode_AsUTF8(tp_qualname), "HeapTypeNameType") == 0); Py_DECREF(tp_qualname); PyObject *spec_name = PyUnicode_FromString(HeapTypeNameType_Spec.name); if (spec_name == NULL) { goto done; } if (PyObject_SetAttrString(HeapTypeNameType, "__qualname__", spec_name) < 0) { Py_DECREF(spec_name); goto done; } tp_qualname = PyType_GetQualName((PyTypeObject *)HeapTypeNameType); assert(strcmp(PyUnicode_AsUTF8(tp_qualname), "_testcapi.HeapTypeNameType") == 0); Py_DECREF(spec_name); Py_DECREF(tp_qualname); done: Py_DECREF(HeapTypeNameType); Py_RETURN_NONE; } static PyObject * pyobject_repr_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) { return PyObject_Repr(NULL); } static PyObject * pyobject_str_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) { return PyObject_Str(NULL); } static PyObject * pyobject_bytes_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) { return PyObject_Bytes(NULL); } static PyObject * set_errno(PyObject *self, PyObject *args) { int new_errno; if (!PyArg_ParseTuple(args, "i:set_errno", &new_errno)) return NULL; errno = new_errno; Py_RETURN_NONE; } /* test_thread_state spawns a thread of its own, and that thread releases * `thread_done` when it's finished. The driver code has to know when the * thread finishes, because the thread uses a PyObject (the callable) that * may go away when the driver finishes. The former lack of this explicit * synchronization caused rare segfaults, so rare that they were seen only * on a Mac buildbot (although they were possible on any box). */ static PyThread_type_lock thread_done = NULL; static int _make_call(void *callable) { PyObject *rc; int success; PyGILState_STATE s = PyGILState_Ensure(); rc = PyObject_CallNoArgs((PyObject *)callable); success = (rc != NULL); Py_XDECREF(rc); PyGILState_Release(s); return success; } /* Same thing, but releases `thread_done` when it returns. This variant * should be called only from threads spawned by test_thread_state(). */ static void _make_call_from_thread(void *callable) { _make_call(callable); PyThread_release_lock(thread_done); } 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", Py_TYPE(fn)->tp_name); return NULL; } thread_done = PyThread_allocate_lock(); if (thread_done == NULL) return PyErr_NoMemory(); PyThread_acquire_lock(thread_done, 1); /* 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 */ success &= _make_call(fn); /* Do it all again, but this time with the thread-lock released */ Py_BEGIN_ALLOW_THREADS success &= _make_call(fn); PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */ Py_END_ALLOW_THREADS /* And once more with and without a thread XXX - should use a lock and work out exactly what we are trying to test */ Py_BEGIN_ALLOW_THREADS PyThread_start_new_thread(_make_call_from_thread, fn); success &= _make_call(fn); PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */ Py_END_ALLOW_THREADS /* Release lock we acquired above. This is required on HP-UX. */ PyThread_release_lock(thread_done); PyThread_free_lock(thread_done); if (!success) return NULL; Py_RETURN_NONE; } #ifndef MS_WINDOWS static PyThread_type_lock wait_done = NULL; static void wait_for_lock(void *unused) { PyThread_acquire_lock(wait_done, 1); PyThread_release_lock(wait_done); PyThread_free_lock(wait_done); wait_done = NULL; } // These can be used to test things that care about the existence of another // thread that the threading module doesn't know about. static PyObject * spawn_pthread_waiter(PyObject *self, PyObject *Py_UNUSED(ignored)) { if (wait_done) { PyErr_SetString(PyExc_RuntimeError, "thread already running"); return NULL; } wait_done = PyThread_allocate_lock(); if (wait_done == NULL) return PyErr_NoMemory(); PyThread_acquire_lock(wait_done, 1); PyThread_start_new_thread(wait_for_lock, NULL); Py_RETURN_NONE; } static PyObject * end_spawned_pthread(PyObject *self, PyObject *Py_UNUSED(ignored)) { if (!wait_done) { PyErr_SetString(PyExc_RuntimeError, "call _spawn_pthread_waiter 1st"); return NULL; } PyThread_release_lock(wait_done); Py_RETURN_NONE; } #endif // not MS_WINDOWS /* test Py_AddPendingCalls using threads */ static int _pending_callback(void *arg) { /* we assume the argument is callable object to which we own a reference */ PyObject *callable = (PyObject *)arg; PyObject *r = PyObject_CallNoArgs(callable); Py_DECREF(callable); Py_XDECREF(r); return r != NULL ? 0 : -1; } /* The following requests n callbacks to _pending_callback. It can be * run from any python thread. */ static PyObject * pending_threadfunc(PyObject *self, PyObject *arg) { PyObject *callable; int r; if (PyArg_ParseTuple(arg, "O", &callable) == 0) return NULL; /* create the reference for the callbackwhile we hold the lock */ Py_INCREF(callable); Py_BEGIN_ALLOW_THREADS r = Py_AddPendingCall(&_pending_callback, callable); Py_END_ALLOW_THREADS if (r<0) { Py_DECREF(callable); /* unsuccessful add, destroy the extra reference */ Py_RETURN_FALSE; } Py_RETURN_TRUE; } /* Test PyOS_string_to_double. */ static PyObject * test_string_to_double(PyObject *self, PyObject *Py_UNUSED(ignored)) { double result; const char *msg; #define CHECK_STRING(STR, expected) \ result = PyOS_string_to_double(STR, NULL, NULL); \ if (result == -1.0 && PyErr_Occurred()) \ return NULL; \ if (result != (double)expected) { \ msg = "conversion of " STR " to float failed"; \ goto fail; \ } #define CHECK_INVALID(STR) \ result = PyOS_string_to_double(STR, NULL, NULL); \ if (result == -1.0 && PyErr_Occurred()) { \ if (PyErr_ExceptionMatches(PyExc_ValueError)) \ PyErr_Clear(); \ else \ return NULL; \ } \ else { \ msg = "conversion of " STR " didn't raise ValueError"; \ goto fail; \ } CHECK_STRING("0.1", 0.1); CHECK_STRING("1.234", 1.234); CHECK_STRING("-1.35", -1.35); CHECK_STRING(".1e01", 1.0); CHECK_STRING("2.e-2", 0.02); CHECK_INVALID(" 0.1"); CHECK_INVALID("\t\n-3"); CHECK_INVALID(".123 "); CHECK_INVALID("3\n"); CHECK_INVALID("123abc"); Py_RETURN_NONE; fail: return raiseTestError("test_string_to_double", msg); #undef CHECK_STRING #undef CHECK_INVALID } /* Coverage testing of capsule objects. */ static const char *capsule_name = "capsule name"; static char *capsule_pointer = "capsule pointer"; static char *capsule_context = "capsule context"; static const char *capsule_error = NULL; static int capsule_destructor_call_count = 0; static void capsule_destructor(PyObject *o) { capsule_destructor_call_count++; if (PyCapsule_GetContext(o) != capsule_context) { capsule_error = "context did not match in destructor!"; } else if (PyCapsule_GetDestructor(o) != capsule_destructor) { capsule_error = "destructor did not match in destructor! (woah!)"; } else if (PyCapsule_GetName(o) != capsule_name) { capsule_error = "name did not match in destructor!"; } else if (PyCapsule_GetPointer(o, capsule_name) != capsule_pointer) { capsule_error = "pointer did not match in destructor!"; } } typedef struct { char *name; char *module; char *attribute; } known_capsule; static PyObject * test_capsule(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyObject *object; const char *error = NULL; void *pointer; void *pointer2; known_capsule known_capsules[] = { #define KNOWN_CAPSULE(module, name) { module "." name, module, name } KNOWN_CAPSULE("_socket", "CAPI"), KNOWN_CAPSULE("_curses", "_C_API"), KNOWN_CAPSULE("datetime", "datetime_CAPI"), { NULL, NULL }, }; known_capsule *known = &known_capsules[0]; #define FAIL(x) { error = (x); goto exit; } #define CHECK_DESTRUCTOR \ if (capsule_error) { \ FAIL(capsule_error); \ } \ else if (!capsule_destructor_call_count) { \ FAIL("destructor not called!"); \ } \ capsule_destructor_call_count = 0; \ object = PyCapsule_New(capsule_pointer, capsule_name, capsule_destructor); PyCapsule_SetContext(object, capsule_context); capsule_destructor(object); CHECK_DESTRUCTOR; Py_DECREF(object); CHECK_DESTRUCTOR; object = PyCapsule_New(known, "ignored", NULL); PyCapsule_SetPointer(object, capsule_pointer); PyCapsule_SetName(object, capsule_name); PyCapsule_SetDestructor(object, capsule_destructor); PyCapsule_SetContext(object, capsule_context); capsule_destructor(object); CHECK_DESTRUCTOR; /* intentionally access using the wrong name */ pointer2 = PyCapsule_GetPointer(object, "the wrong name"); if (!PyErr_Occurred()) { FAIL("PyCapsule_GetPointer should have failed but did not!"); } PyErr_Clear(); if (pointer2) { if (pointer2 == capsule_pointer) { FAIL("PyCapsule_GetPointer should not have" " returned the internal pointer!"); } else { FAIL("PyCapsule_GetPointer should have " "returned NULL pointer but did not!"); } } PyCapsule_SetDestructor(object, NULL); Py_DECREF(object); if (capsule_destructor_call_count) { FAIL("destructor called when it should not have been!"); } for (known = &known_capsules[0]; known->module != NULL; known++) { /* yeah, ordinarily I wouldn't do this either, but it's fine for this test harness. */ static char buffer[256]; #undef FAIL #define FAIL(x) \ { \ sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \ x, known->module, known->attribute); \ error = buffer; \ goto exit; \ } \ PyObject *module = PyImport_ImportModule(known->module); if (module) { pointer = PyCapsule_Import(known->name, 0); if (!pointer) { Py_DECREF(module); FAIL("PyCapsule_GetPointer returned NULL unexpectedly!"); } object = PyObject_GetAttrString(module, known->attribute); if (!object) { Py_DECREF(module); return NULL; } pointer2 = PyCapsule_GetPointer(object, "weebles wobble but they don't fall down"); if (!PyErr_Occurred()) { Py_DECREF(object); Py_DECREF(module); FAIL("PyCapsule_GetPointer should have failed but did not!"); } PyErr_Clear(); if (pointer2) { Py_DECREF(module); Py_DECREF(object); if (pointer2 == pointer) { FAIL("PyCapsule_GetPointer should not have" " returned its internal pointer!"); } else { FAIL("PyCapsule_GetPointer should have" " returned NULL pointer but did not!"); } } Py_DECREF(object); Py_DECREF(module); } else PyErr_Clear(); } exit: if (error) { return raiseTestError("test_capsule", error); } Py_RETURN_NONE; #undef FAIL } #ifdef HAVE_GETTIMEOFDAY /* Profiling of integer performance */ static void print_delta(int test, struct timeval *s, struct timeval *e) { e->tv_sec -= s->tv_sec; e->tv_usec -= s->tv_usec; if (e->tv_usec < 0) { e->tv_sec -=1; e->tv_usec += 1000000; } printf("Test %d: %d.%06ds\n", test, (int)e->tv_sec, (int)e->tv_usec); } static PyObject * profile_int(PyObject *self, PyObject* args) { int i, k; struct timeval start, stop; PyObject *single, **multiple, *op1, *result; /* Test 1: Allocate and immediately deallocate many small integers */ gettimeofday(&start, NULL); for(k=0; k < 20000; k++) for(i=0; i < 1000; i++) { single = PyLong_FromLong(i); Py_DECREF(single); } gettimeofday(&stop, NULL); print_delta(1, &start, &stop); /* Test 2: Allocate and immediately deallocate many large integers */ gettimeofday(&start, NULL); for(k=0; k < 20000; k++) for(i=0; i < 1000; i++) { single = PyLong_FromLong(i+1000000); Py_DECREF(single); } gettimeofday(&stop, NULL); print_delta(2, &start, &stop); /* Test 3: Allocate a few integers, then release them all simultaneously. */ multiple = malloc(sizeof(PyObject*) * 1000); if (multiple == NULL) return PyErr_NoMemory(); gettimeofday(&start, NULL); for(k=0; k < 20000; k++) { for(i=0; i < 1000; i++) { multiple[i] = PyLong_FromLong(i+1000000); } for(i=0; i < 1000; i++) { Py_DECREF(multiple[i]); } } gettimeofday(&stop, NULL); print_delta(3, &start, &stop); free(multiple); /* Test 4: Allocate many integers, then release them all simultaneously. */ multiple = malloc(sizeof(PyObject*) * 1000000); if (multiple == NULL) return PyErr_NoMemory(); gettimeofday(&start, NULL); for(k=0; k < 20; k++) { for(i=0; i < 1000000; i++) { multiple[i] = PyLong_FromLong(i+1000000); } for(i=0; i < 1000000; i++) { Py_DECREF(multiple[i]); } } gettimeofday(&stop, NULL); print_delta(4, &start, &stop); free(multiple); /* Test 5: Allocate many integers < 32000 */ multiple = malloc(sizeof(PyObject*) * 1000000); if (multiple == NULL) return PyErr_NoMemory(); gettimeofday(&start, NULL); for(k=0; k < 10; k++) { for(i=0; i < 1000000; i++) { multiple[i] = PyLong_FromLong(i+1000); } for(i=0; i < 1000000; i++) { Py_DECREF(multiple[i]); } } gettimeofday(&stop, NULL); print_delta(5, &start, &stop); free(multiple); /* Test 6: Perform small int addition */ op1 = PyLong_FromLong(1); gettimeofday(&start, NULL); for(i=0; i < 10000000; i++) { result = PyNumber_Add(op1, op1); Py_DECREF(result); } gettimeofday(&stop, NULL); Py_DECREF(op1); print_delta(6, &start, &stop); /* Test 7: Perform medium int addition */ op1 = PyLong_FromLong(1000); if (op1 == NULL) return NULL; gettimeofday(&start, NULL); for(i=0; i < 10000000; i++) { result = PyNumber_Add(op1, op1); Py_XDECREF(result); } gettimeofday(&stop, NULL); Py_DECREF(op1); print_delta(7, &start, &stop); Py_RETURN_NONE; } #endif /* Issue 6012 */ static PyObject *str1, *str2; static int failing_converter(PyObject *obj, void *arg) { /* Clone str1, then let the conversion fail. */ assert(str1); str2 = Py_NewRef(str1); return 0; } static PyObject* argparsing(PyObject *o, PyObject *args) { PyObject *res; str1 = str2 = NULL; if (!PyArg_ParseTuple(args, "O&O&", PyUnicode_FSConverter, &str1, failing_converter, &str2)) { if (!str2) /* argument converter not called? */ return NULL; /* Should be 1 */ res = PyLong_FromSsize_t(Py_REFCNT(str2)); Py_DECREF(str2); PyErr_Clear(); return res; } Py_RETURN_NONE; } /* To test that the result of PyCode_NewEmpty has the right members. */ static PyObject * code_newempty(PyObject *self, PyObject *args) { const char *filename; const char *funcname; int firstlineno; if (!PyArg_ParseTuple(args, "ssi:code_newempty", &filename, &funcname, &firstlineno)) return NULL; return (PyObject *)PyCode_NewEmpty(filename, funcname, firstlineno); } static PyObject * make_memoryview_from_NULL_pointer(PyObject *self, PyObject *Py_UNUSED(ignored)) { Py_buffer info; if (PyBuffer_FillInfo(&info, NULL, NULL, 1, 1, PyBUF_FULL_RO) < 0) return NULL; return PyMemoryView_FromBuffer(&info); } static PyObject * test_from_contiguous(PyObject* self, PyObject *Py_UNUSED(ignored)) { int data[9] = {-1,-1,-1,-1,-1,-1,-1,-1,-1}; int init[5] = {0, 1, 2, 3, 4}; Py_ssize_t itemsize = sizeof(int); Py_ssize_t shape = 5; Py_ssize_t strides = 2 * itemsize; Py_buffer view = { data, NULL, 5 * itemsize, itemsize, 1, 1, NULL, &shape, &strides, NULL, NULL }; int *ptr; int i; PyBuffer_FromContiguous(&view, init, view.len, 'C'); ptr = view.buf; for (i = 0; i < 5; i++) { if (ptr[2*i] != i) { PyErr_SetString(TestError, "test_from_contiguous: incorrect result"); return NULL; } } view.buf = &data[8]; view.strides[0] = -2 * itemsize; PyBuffer_FromContiguous(&view, init, view.len, 'C'); ptr = view.buf; for (i = 0; i < 5; i++) { if (*(ptr-2*i) != i) { PyErr_SetString(TestError, "test_from_contiguous: incorrect result"); return NULL; } } Py_RETURN_NONE; } #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__) static PyObject * test_pep3118_obsolete_write_locks(PyObject* self, PyObject *Py_UNUSED(ignored)) { PyObject *b; char *dummy[1]; int ret, match; /* PyBuffer_FillInfo() */ ret = PyBuffer_FillInfo(NULL, NULL, dummy, 1, 0, PyBUF_SIMPLE); match = PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_BufferError); PyErr_Clear(); if (ret != -1 || match == 0) goto error; /* bytesiobuf_getbuffer() */ PyTypeObject *type = (PyTypeObject *)_PyImport_GetModuleAttrString( "_io", "_BytesIOBuffer"); if (type == NULL) { return NULL; } b = type->tp_alloc(type, 0); Py_DECREF(type); if (b == NULL) { return NULL; } ret = PyObject_GetBuffer(b, NULL, PyBUF_SIMPLE); Py_DECREF(b); match = PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_BufferError); PyErr_Clear(); if (ret != -1 || match == 0) goto error; Py_RETURN_NONE; error: PyErr_SetString(TestError, "test_pep3118_obsolete_write_locks: failure"); return NULL; } #endif /* This tests functions that historically supported write locks. It is wrong to call getbuffer() with view==NULL and a compliant getbufferproc is entitled to segfault in that case. */ static PyObject * getbuffer_with_null_view(PyObject* self, PyObject *obj) { if (PyObject_GetBuffer(obj, NULL, PyBUF_SIMPLE) < 0) return NULL; Py_RETURN_NONE; } /* PyBuffer_SizeFromFormat() */ static PyObject * test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args) { const char *format; Py_ssize_t result; if (!PyArg_ParseTuple(args, "s:test_PyBuffer_SizeFromFormat", &format)) { return NULL; } result = PyBuffer_SizeFromFormat(format); if (result == -1) { return NULL; } return PyLong_FromSsize_t(result); } /* Test that the fatal error from not having a current thread doesn't cause an infinite loop. Run via Lib/test/test_capi.py */ static PyObject * crash_no_current_thread(PyObject *self, PyObject *Py_UNUSED(ignored)) { Py_BEGIN_ALLOW_THREADS /* Using PyThreadState_Get() directly allows the test to pass in !pydebug mode. However, the test only actually tests anything in pydebug mode, since that's where the infinite loop was in the first place. */ PyThreadState_Get(); Py_END_ALLOW_THREADS return NULL; } /* Test that the GILState thread and the "current" thread match. */ static PyObject * test_current_tstate_matches(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyThreadState *orig_tstate = PyThreadState_Get(); if (orig_tstate != PyGILState_GetThisThreadState()) { PyErr_SetString(PyExc_RuntimeError, "current thread state doesn't match GILState"); return NULL; } const char *err = NULL; PyThreadState_Swap(NULL); PyThreadState *substate = Py_NewInterpreter(); if (substate != PyThreadState_Get()) { err = "subinterpreter thread state not current"; goto finally; } if (substate != PyGILState_GetThisThreadState()) { err = "subinterpreter thread state doesn't match GILState"; goto finally; } finally: Py_EndInterpreter(substate); PyThreadState_Swap(orig_tstate); if (err != NULL) { PyErr_SetString(PyExc_RuntimeError, err); return NULL; } Py_RETURN_NONE; } /* To run some code in a sub-interpreter. */ static PyObject * run_in_subinterp(PyObject *self, PyObject *args) { const char *code; int r; PyThreadState *substate, *mainstate; /* only initialise 'cflags.cf_flags' to test backwards compatibility */ PyCompilerFlags cflags = {0}; if (!PyArg_ParseTuple(args, "s:run_in_subinterp", &code)) return NULL; mainstate = PyThreadState_Get(); PyThreadState_Swap(NULL); substate = Py_NewInterpreter(); if (substate == NULL) { /* Since no new thread state was created, there is no exception to propagate; raise a fresh one after swapping in the old thread state. */ PyThreadState_Swap(mainstate); PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed"); return NULL; } r = PyRun_SimpleStringFlags(code, &cflags); Py_EndInterpreter(substate); PyThreadState_Swap(mainstate); return PyLong_FromLong(r); } /* To run some code in a sub-interpreter. */ static PyObject * run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs) { const char *code; int use_main_obmalloc = -1; int allow_fork = -1; int allow_exec = -1; int allow_threads = -1; int allow_daemon_threads = -1; int check_multi_interp_extensions = -1; int r; PyThreadState *substate, *mainstate; /* only initialise 'cflags.cf_flags' to test backwards compatibility */ PyCompilerFlags cflags = {0}; static char *kwlist[] = {"code", "use_main_obmalloc", "allow_fork", "allow_exec", "allow_threads", "allow_daemon_threads", "check_multi_interp_extensions", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s$pppppp:run_in_subinterp_with_config", kwlist, &code, &use_main_obmalloc, &allow_fork, &allow_exec, &allow_threads, &allow_daemon_threads, &check_multi_interp_extensions)) { return NULL; } if (use_main_obmalloc < 0) { PyErr_SetString(PyExc_ValueError, "missing use_main_obmalloc"); return NULL; } if (allow_fork < 0) { PyErr_SetString(PyExc_ValueError, "missing allow_fork"); return NULL; } if (allow_exec < 0) { PyErr_SetString(PyExc_ValueError, "missing allow_exec"); return NULL; } if (allow_threads < 0) { PyErr_SetString(PyExc_ValueError, "missing allow_threads"); return NULL; } if (allow_daemon_threads < 0) { PyErr_SetString(PyExc_ValueError, "missing allow_daemon_threads"); return NULL; } if (check_multi_interp_extensions < 0) { PyErr_SetString(PyExc_ValueError, "missing check_multi_interp_extensions"); return NULL; } mainstate = PyThreadState_Get(); PyThreadState_Swap(NULL); const _PyInterpreterConfig config = { .use_main_obmalloc = use_main_obmalloc, .allow_fork = allow_fork, .allow_exec = allow_exec, .allow_threads = allow_threads, .allow_daemon_threads = allow_daemon_threads, .check_multi_interp_extensions = check_multi_interp_extensions, }; PyStatus status = _Py_NewInterpreterFromConfig(&substate, &config); if (PyStatus_Exception(status)) { /* Since no new thread state was created, there is no exception to propagate; raise a fresh one after swapping in the old thread state. */ PyThreadState_Swap(mainstate); _PyErr_SetFromPyStatus(status); PyObject *exc = PyErr_GetRaisedException(); PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed"); _PyErr_ChainExceptions1(exc); return NULL; } assert(substate != NULL); r = PyRun_SimpleStringFlags(code, &cflags); Py_EndInterpreter(substate); PyThreadState_Swap(mainstate); return PyLong_FromLong(r); } static void _xid_capsule_destructor(PyObject *capsule) { _PyCrossInterpreterData *data = \ (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); if (data != NULL) { assert(_PyCrossInterpreterData_Release(data) == 0); PyMem_Free(data); } } static PyObject * get_crossinterp_data(PyObject *self, PyObject *args) { PyObject *obj = NULL; if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) { return NULL; } _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); if (data == NULL) { PyErr_NoMemory(); return NULL; } if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { PyMem_Free(data); return NULL; } PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor); if (capsule == NULL) { assert(_PyCrossInterpreterData_Release(data) == 0); PyMem_Free(data); } return capsule; } static PyObject * restore_crossinterp_data(PyObject *self, PyObject *args) { PyObject *capsule = NULL; if (!PyArg_ParseTuple(args, "O:restore_crossinterp_data", &capsule)) { return NULL; } _PyCrossInterpreterData *data = \ (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); if (data == NULL) { return NULL; } return _PyCrossInterpreterData_NewObject(data); } static void slot_tp_del(PyObject *self) { PyObject *del, *res; /* Temporarily resurrect the object. */ assert(Py_REFCNT(self) == 0); Py_SET_REFCNT(self, 1); /* Save the current exception, if any. */ PyObject *exc = PyErr_GetRaisedException(); PyObject *tp_del = PyUnicode_InternFromString("__tp_del__"); if (tp_del == NULL) { PyErr_WriteUnraisable(NULL); PyErr_SetRaisedException(exc); return; } /* Execute __del__ method, if any. */ del = _PyType_Lookup(Py_TYPE(self), tp_del); Py_DECREF(tp_del); if (del != NULL) { res = PyObject_CallOneArg(del, self); if (res == NULL) PyErr_WriteUnraisable(del); else Py_DECREF(res); } /* Restore the saved exception. */ PyErr_SetRaisedException(exc); /* Undo the temporary resurrection; can't use DECREF here, it would * cause a recursive call. */ assert(Py_REFCNT(self) > 0); Py_SET_REFCNT(self, Py_REFCNT(self) - 1); if (Py_REFCNT(self) == 0) { /* this is the normal path out */ return; } /* __del__ resurrected it! Make it look like the original Py_DECREF * never happened. */ { Py_ssize_t refcnt = Py_REFCNT(self); _Py_NewReferenceNoTotal(self); Py_SET_REFCNT(self, refcnt); } assert(!PyType_IS_GC(Py_TYPE(self)) || PyObject_GC_IsTracked(self)); } static PyObject * with_tp_del(PyObject *self, PyObject *args) { PyObject *obj; PyTypeObject *tp; if (!PyArg_ParseTuple(args, "O:with_tp_del", &obj)) return NULL; tp = (PyTypeObject *) obj; if (!PyType_Check(obj) || !PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) { PyErr_Format(PyExc_TypeError, "heap type expected, got %R", obj); return NULL; } tp->tp_del = slot_tp_del; return Py_NewRef(obj); } static PyObject * without_gc(PyObject *Py_UNUSED(self), PyObject *obj) { PyTypeObject *tp = (PyTypeObject*)obj; if (!PyType_Check(obj) || !PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) { return PyErr_Format(PyExc_TypeError, "heap type expected, got %R", obj); } if (PyType_IS_GC(tp)) { // Don't try this at home, kids: tp->tp_flags -= Py_TPFLAGS_HAVE_GC; tp->tp_free = PyObject_Del; tp->tp_traverse = NULL; tp->tp_clear = NULL; } assert(!PyType_IS_GC(tp)); return Py_NewRef(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) { return Py_NewRef(ob); } static PyObject * test_xincref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored)) { PyObject *obj = PyLong_FromLong(0); Py_XINCREF(_test_incref(obj)); Py_DECREF(obj); Py_DECREF(obj); Py_DECREF(obj); Py_RETURN_NONE; } static PyObject * test_incref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored)) { PyObject *obj = PyLong_FromLong(0); Py_INCREF(_test_incref(obj)); Py_DECREF(obj); Py_DECREF(obj); Py_DECREF(obj); Py_RETURN_NONE; } static PyObject * test_xdecref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored)) { Py_XDECREF(PyLong_FromLong(0)); Py_RETURN_NONE; } static PyObject * test_decref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored)) { Py_DECREF(PyLong_FromLong(0)); Py_RETURN_NONE; } static PyObject * test_structseq_newtype_doesnt_leak(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { PyStructSequence_Desc descr; PyStructSequence_Field descr_fields[3]; descr_fields[0] = (PyStructSequence_Field){"foo", "foo value"}; descr_fields[1] = (PyStructSequence_Field){NULL, "some hidden value"}; descr_fields[2] = (PyStructSequence_Field){0, NULL}; descr.name = "_testcapi.test_descr"; descr.doc = "This is used to test for memory leaks in NewType"; descr.fields = descr_fields; descr.n_in_sequence = 1; PyTypeObject* structseq_type = PyStructSequence_NewType(&descr); assert(structseq_type != NULL); assert(PyType_Check(structseq_type)); assert(PyType_FastSubclass(structseq_type, Py_TPFLAGS_TUPLE_SUBCLASS)); Py_DECREF(structseq_type); Py_RETURN_NONE; } static PyObject * test_structseq_newtype_null_descr_doc(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { PyStructSequence_Field descr_fields[1] = { (PyStructSequence_Field){NULL, NULL} }; // Test specifically for NULL .doc field. PyStructSequence_Desc descr = {"_testcapi.test_descr", NULL, &descr_fields[0], 0}; PyTypeObject* structseq_type = PyStructSequence_NewType(&descr); assert(structseq_type != NULL); assert(PyType_Check(structseq_type)); assert(PyType_FastSubclass(structseq_type, Py_TPFLAGS_TUPLE_SUBCLASS)); Py_DECREF(structseq_type); Py_RETURN_NONE; } static PyObject * test_incref_decref_API(PyObject *ob, PyObject *Py_UNUSED(ignored)) { PyObject *obj = PyLong_FromLong(0); Py_IncRef(obj); Py_DecRef(obj); Py_DecRef(obj); Py_RETURN_NONE; } typedef struct { PyThread_type_lock start_event; PyThread_type_lock exit_event; PyObject *callback; } test_c_thread_t; static void temporary_c_thread(void *data) { test_c_thread_t *test_c_thread = data; PyGILState_STATE state; PyObject *res; PyThread_release_lock(test_c_thread->start_event); /* Allocate a Python thread state for this thread */ state = PyGILState_Ensure(); res = PyObject_CallNoArgs(test_c_thread->callback); Py_CLEAR(test_c_thread->callback); if (res == NULL) { PyErr_Print(); } else { Py_DECREF(res); } /* Destroy the Python thread state for this thread */ PyGILState_Release(state); PyThread_release_lock(test_c_thread->exit_event); } static test_c_thread_t test_c_thread; static PyObject * call_in_temporary_c_thread(PyObject *self, PyObject *args) { PyObject *res = NULL; PyObject *callback = NULL; long thread; int wait = 1; if (!PyArg_ParseTuple(args, "O|i", &callback, &wait)) { return NULL; } test_c_thread.start_event = PyThread_allocate_lock(); test_c_thread.exit_event = PyThread_allocate_lock(); test_c_thread.callback = NULL; if (!test_c_thread.start_event || !test_c_thread.exit_event) { PyErr_SetString(PyExc_RuntimeError, "could not allocate lock"); goto exit; } test_c_thread.callback = Py_NewRef(callback); PyThread_acquire_lock(test_c_thread.start_event, 1); PyThread_acquire_lock(test_c_thread.exit_event, 1); thread = PyThread_start_new_thread(temporary_c_thread, &test_c_thread); if (thread == -1) { PyErr_SetString(PyExc_RuntimeError, "unable to start the thread"); PyThread_release_lock(test_c_thread.start_event); PyThread_release_lock(test_c_thread.exit_event); goto exit; } PyThread_acquire_lock(test_c_thread.start_event, 1); PyThread_release_lock(test_c_thread.start_event); if (!wait) { Py_RETURN_NONE; } Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(test_c_thread.exit_event, 1); PyThread_release_lock(test_c_thread.exit_event); Py_END_ALLOW_THREADS res = Py_NewRef(Py_None); exit: Py_CLEAR(test_c_thread.callback); if (test_c_thread.start_event) { PyThread_free_lock(test_c_thread.start_event); test_c_thread.start_event = NULL; } if (test_c_thread.exit_event) { PyThread_free_lock(test_c_thread.exit_event); test_c_thread.exit_event = NULL; } return res; } static PyObject * join_temporary_c_thread(PyObject *self, PyObject *Py_UNUSED(ignored)) { Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(test_c_thread.exit_event, 1); PyThread_release_lock(test_c_thread.exit_event); Py_END_ALLOW_THREADS Py_CLEAR(test_c_thread.callback); PyThread_free_lock(test_c_thread.start_event); test_c_thread.start_event = NULL; PyThread_free_lock(test_c_thread.exit_event); test_c_thread.exit_event = NULL; Py_RETURN_NONE; } /* marshal */ static PyObject* pymarshal_write_long_to_file(PyObject* self, PyObject *args) { long value; PyObject *filename; int version; FILE *fp; if (!PyArg_ParseTuple(args, "lOi:pymarshal_write_long_to_file", &value, &filename, &version)) return NULL; fp = _Py_fopen_obj(filename, "wb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } PyMarshal_WriteLongToFile(value, fp, version); fclose(fp); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; } static PyObject* pymarshal_write_object_to_file(PyObject* self, PyObject *args) { PyObject *obj; PyObject *filename; int version; FILE *fp; if (!PyArg_ParseTuple(args, "OOi:pymarshal_write_object_to_file", &obj, &filename, &version)) return NULL; fp = _Py_fopen_obj(filename, "wb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } PyMarshal_WriteObjectToFile(obj, fp, version); fclose(fp); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; } static PyObject* pymarshal_read_short_from_file(PyObject* self, PyObject *args) { int value; long pos; PyObject *filename; FILE *fp; if (!PyArg_ParseTuple(args, "O:pymarshal_read_short_from_file", &filename)) return NULL; fp = _Py_fopen_obj(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } value = PyMarshal_ReadShortFromFile(fp); pos = ftell(fp); fclose(fp); if (PyErr_Occurred()) return NULL; return Py_BuildValue("il", value, pos); } static PyObject* pymarshal_read_long_from_file(PyObject* self, PyObject *args) { long value, pos; PyObject *filename; FILE *fp; if (!PyArg_ParseTuple(args, "O:pymarshal_read_long_from_file", &filename)) return NULL; fp = _Py_fopen_obj(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } value = PyMarshal_ReadLongFromFile(fp); pos = ftell(fp); fclose(fp); if (PyErr_Occurred()) return NULL; return Py_BuildValue("ll", value, pos); } static PyObject* pymarshal_read_last_object_from_file(PyObject* self, PyObject *args) { PyObject *obj; long pos; PyObject *filename; FILE *fp; if (!PyArg_ParseTuple(args, "O:pymarshal_read_last_object_from_file", &filename)) return NULL; fp = _Py_fopen_obj(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } obj = PyMarshal_ReadLastObjectFromFile(fp); pos = ftell(fp); fclose(fp); return Py_BuildValue("Nl", obj, pos); } static PyObject* pymarshal_read_object_from_file(PyObject* self, PyObject *args) { PyObject *obj; long pos; PyObject *filename; FILE *fp; if (!PyArg_ParseTuple(args, "O:pymarshal_read_object_from_file", &filename)) return NULL; fp = _Py_fopen_obj(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } obj = PyMarshal_ReadObjectFromFile(fp); pos = ftell(fp); fclose(fp); return Py_BuildValue("Nl", obj, pos); } static PyObject* return_null_without_error(PyObject *self, PyObject *args) { /* invalid call: return NULL without setting an error, * _Py_CheckFunctionResult() must detect such bug at runtime. */ PyErr_Clear(); return NULL; } static PyObject* return_result_with_error(PyObject *self, PyObject *args) { /* invalid call: return a result with an error set, * _Py_CheckFunctionResult() must detect such bug at runtime. */ PyErr_SetNone(PyExc_ValueError); Py_RETURN_NONE; } static PyObject* getitem_with_error(PyObject *self, PyObject *args) { PyObject *map, *key; if (!PyArg_ParseTuple(args, "OO", &map, &key)) { return NULL; } PyErr_SetString(PyExc_ValueError, "bug"); return PyObject_GetItem(map, key); } static PyObject * dict_get_version(PyObject *self, PyObject *args) { PyDictObject *dict; uint64_t version; if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict)) return NULL; _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS version = dict->ma_version_tag; _Py_COMP_DIAG_POP static_assert(sizeof(unsigned long long) >= sizeof(version), "version is larger than unsigned long long"); return PyLong_FromUnsignedLongLong((unsigned long long)version); } static PyObject * raise_SIGINT_then_send_None(PyObject *self, PyObject *args) { PyGenObject *gen; if (!PyArg_ParseTuple(args, "O!", &PyGen_Type, &gen)) return NULL; /* This is used in a test to check what happens if a signal arrives just as we're in the process of entering a yield from chain (see bpo-30039). Needs to be done in C, because: - we don't have a Python wrapper for raise() - we need to make sure that the Python-level signal handler doesn't run *before* we enter the generator frame, which is impossible in Python because we check for signals before every bytecode operation. */ raise(SIGINT); return PyObject_CallMethod((PyObject *)gen, "send", "O", Py_None); } static PyObject* stack_pointer(PyObject *self, PyObject *args) { int v = 5; return PyLong_FromVoidPtr(&v); } #ifdef W_STOPCODE static PyObject* py_w_stopcode(PyObject *self, PyObject *args) { int sig, status; if (!PyArg_ParseTuple(args, "i", &sig)) { return NULL; } status = W_STOPCODE(sig); return PyLong_FromLong(status); } #endif static PyObject * get_mapping_keys(PyObject* self, PyObject *obj) { return PyMapping_Keys(obj); } static PyObject * get_mapping_values(PyObject* self, PyObject *obj) { return PyMapping_Values(obj); } static PyObject * get_mapping_items(PyObject* self, PyObject *obj) { return PyMapping_Items(obj); } static PyObject * test_mapping_has_key_string(PyObject *self, PyObject *Py_UNUSED(args)) { PyObject *context = PyDict_New(); PyObject *val = PyLong_FromLong(1); // Since this uses `const char*` it is easier to test this in C: PyDict_SetItemString(context, "a", val); if (!PyMapping_HasKeyString(context, "a")) { PyErr_SetString(PyExc_RuntimeError, "Existing mapping key does not exist"); return NULL; } if (PyMapping_HasKeyString(context, "b")) { PyErr_SetString(PyExc_RuntimeError, "Missing mapping key exists"); return NULL; } Py_DECREF(val); Py_DECREF(context); Py_RETURN_NONE; } static PyObject * mapping_has_key(PyObject* self, PyObject *args) { PyObject *context, *key; if (!PyArg_ParseTuple(args, "OO", &context, &key)) { return NULL; } return PyLong_FromLong(PyMapping_HasKey(context, key)); } static PyObject * sequence_set_slice(PyObject* self, PyObject *args) { PyObject *sequence, *obj; Py_ssize_t i1, i2; if (!PyArg_ParseTuple(args, "OnnO", &sequence, &i1, &i2, &obj)) { return NULL; } int res = PySequence_SetSlice(sequence, i1, i2, obj); if (res == -1) { return NULL; } Py_RETURN_NONE; } static PyObject * sequence_del_slice(PyObject* self, PyObject *args) { PyObject *sequence; Py_ssize_t i1, i2; if (!PyArg_ParseTuple(args, "Onn", &sequence, &i1, &i2)) { return NULL; } int res = PySequence_DelSlice(sequence, i1, i2); if (res == -1) { return NULL; } Py_RETURN_NONE; } static PyObject * test_pythread_tss_key_state(PyObject *self, PyObject *args) { Py_tss_t tss_key = Py_tss_NEEDS_INIT; if (PyThread_tss_is_created(&tss_key)) { return raiseTestError("test_pythread_tss_key_state", "TSS key not in an uninitialized state at " "creation time"); } if (PyThread_tss_create(&tss_key) != 0) { PyErr_SetString(PyExc_RuntimeError, "PyThread_tss_create failed"); return NULL; } if (!PyThread_tss_is_created(&tss_key)) { return raiseTestError("test_pythread_tss_key_state", "PyThread_tss_create succeeded, " "but with TSS key in an uninitialized state"); } if (PyThread_tss_create(&tss_key) != 0) { return raiseTestError("test_pythread_tss_key_state", "PyThread_tss_create unsuccessful with " "an already initialized key"); } #define CHECK_TSS_API(expr) \ (void)(expr); \ if (!PyThread_tss_is_created(&tss_key)) { \ return raiseTestError("test_pythread_tss_key_state", \ "TSS key initialization state was not " \ "preserved after calling " #expr); } CHECK_TSS_API(PyThread_tss_set(&tss_key, NULL)); CHECK_TSS_API(PyThread_tss_get(&tss_key)); #undef CHECK_TSS_API PyThread_tss_delete(&tss_key); if (PyThread_tss_is_created(&tss_key)) { return raiseTestError("test_pythread_tss_key_state", "PyThread_tss_delete called, but did not " "set the key state to uninitialized"); } Py_tss_t *ptr_key = PyThread_tss_alloc(); if (ptr_key == NULL) { PyErr_SetString(PyExc_RuntimeError, "PyThread_tss_alloc failed"); return NULL; } if (PyThread_tss_is_created(ptr_key)) { return raiseTestError("test_pythread_tss_key_state", "TSS key not in an uninitialized state at " "allocation time"); } PyThread_tss_free(ptr_key); ptr_key = NULL; Py_RETURN_NONE; } static PyObject* new_hamt(PyObject *self, PyObject *args) { return _PyContext_NewHamtForTests(); } /* def bad_get(self, obj, cls): cls() return repr(self) */ static PyObject* bad_get(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *self, *obj, *cls; if (!_PyArg_UnpackStack(args, nargs, "bad_get", 3, 3, &self, &obj, &cls)) { return NULL; } PyObject *res = PyObject_CallNoArgs(cls); if (res == NULL) { return NULL; } Py_DECREF(res); return PyObject_Repr(self); } #ifdef Py_REF_DEBUG static PyObject * negative_refcount(PyObject *self, PyObject *Py_UNUSED(args)) { PyObject *obj = PyUnicode_FromString("negative_refcount"); if (obj == NULL) { return NULL; } assert(Py_REFCNT(obj) == 1); Py_SET_REFCNT(obj, 0); /* Py_DECREF() must call _Py_NegativeRefcount() and abort Python */ Py_DECREF(obj); Py_RETURN_NONE; } #endif static PyObject * sequence_getitem(PyObject *self, PyObject *args) { PyObject *seq; Py_ssize_t i; if (!PyArg_ParseTuple(args, "On", &seq, &i)) { return NULL; } return PySequence_GetItem(seq, i); } static PyObject * sequence_setitem(PyObject *self, PyObject *args) { Py_ssize_t i; PyObject *seq, *val; if (!PyArg_ParseTuple(args, "OnO", &seq, &i, &val)) { return NULL; } if (PySequence_SetItem(seq, i, val)) { return NULL; } Py_RETURN_NONE; } static PyObject * sequence_delitem(PyObject *self, PyObject *args) { Py_ssize_t i; PyObject *seq; if (!PyArg_ParseTuple(args, "On", &seq, &i)) { return NULL; } if (PySequence_DelItem(seq, i)) { return NULL; } Py_RETURN_NONE; } static PyObject * hasattr_string(PyObject *self, PyObject* args) { PyObject* obj; PyObject* attr_name; if (!PyArg_UnpackTuple(args, "hasattr_string", 2, 2, &obj, &attr_name)) { return NULL; } if (!PyUnicode_Check(attr_name)) { PyErr_SetString(PyExc_TypeError, "attribute name must a be string"); return PyErr_Occurred(); } const char *name_str = PyUnicode_AsUTF8(attr_name); if (PyObject_HasAttrString(obj, name_str)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /* Functions for testing C calling conventions (METH_*) are named meth_*, * e.g. "meth_varargs" for METH_VARARGS. * * They all return a tuple of their C-level arguments, with None instead * of NULL and Python tuples instead of C arrays. */ static PyObject* _null_to_none(PyObject* obj) { if (obj == NULL) { Py_RETURN_NONE; } return Py_NewRef(obj); } static PyObject* meth_varargs(PyObject* self, PyObject* args) { return Py_BuildValue("NO", _null_to_none(self), args); } static PyObject* meth_varargs_keywords(PyObject* self, PyObject* args, PyObject* kwargs) { return Py_BuildValue("NON", _null_to_none(self), args, _null_to_none(kwargs)); } static PyObject* meth_o(PyObject* self, PyObject* obj) { return Py_BuildValue("NO", _null_to_none(self), obj); } static PyObject* meth_noargs(PyObject* self, PyObject* ignored) { return _null_to_none(self); } static PyObject* _fastcall_to_tuple(PyObject* const* args, Py_ssize_t nargs) { PyObject *tuple = PyTuple_New(nargs); if (tuple == NULL) { return NULL; } for (Py_ssize_t i=0; i < nargs; i++) { Py_INCREF(args[i]); PyTuple_SET_ITEM(tuple, i, args[i]); } return tuple; } static PyObject* meth_fastcall(PyObject* self, PyObject* const* args, Py_ssize_t nargs) { return Py_BuildValue( "NN", _null_to_none(self), _fastcall_to_tuple(args, nargs) ); } static PyObject* meth_fastcall_keywords(PyObject* self, PyObject* const* args, Py_ssize_t nargs, PyObject* kwargs) { PyObject *pyargs = _fastcall_to_tuple(args, nargs); if (pyargs == NULL) { return NULL; } assert(args != NULL || nargs == 0); PyObject* const* args_offset = args == NULL ? NULL : args + nargs; PyObject *pykwargs = PyObject_Vectorcall((PyObject*)&PyDict_Type, args_offset, 0, kwargs); return Py_BuildValue("NNN", _null_to_none(self), pyargs, pykwargs); } static PyObject* pynumber_tobase(PyObject *module, PyObject *args) { PyObject *obj; int base; if (!PyArg_ParseTuple(args, "Oi:pynumber_tobase", &obj, &base)) { return NULL; } return PyNumber_ToBase(obj, base); } static PyObject* test_set_type_size(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyObject *obj = PyList_New(0); if (obj == NULL) { return NULL; } // Ensure that following tests don't modify the object, // to ensure that Py_DECREF() will not crash. assert(Py_TYPE(obj) == &PyList_Type); assert(Py_SIZE(obj) == 0); // bpo-39573: Test Py_SET_TYPE() and Py_SET_SIZE() functions. Py_SET_TYPE(obj, &PyList_Type); Py_SET_SIZE(obj, 0); Py_DECREF(obj); Py_RETURN_NONE; } // Test Py_CLEAR() macro static PyObject* test_py_clear(PyObject *self, PyObject *Py_UNUSED(ignored)) { // simple case with a variable PyObject *obj = PyList_New(0); if (obj == NULL) { return NULL; } Py_CLEAR(obj); assert(obj == NULL); // gh-98724: complex case, Py_CLEAR() argument has a side effect PyObject* array[1]; array[0] = PyList_New(0); if (array[0] == NULL) { return NULL; } PyObject **p = array; Py_CLEAR(*p++); assert(array[0] == NULL); assert(p == array + 1); Py_RETURN_NONE; } // Test Py_SETREF() and Py_XSETREF() macros, similar to test_py_clear() static PyObject* test_py_setref(PyObject *self, PyObject *Py_UNUSED(ignored)) { // Py_SETREF() simple case with a variable PyObject *obj = PyList_New(0); if (obj == NULL) { return NULL; } Py_SETREF(obj, NULL); assert(obj == NULL); // Py_XSETREF() simple case with a variable PyObject *obj2 = PyList_New(0); if (obj2 == NULL) { return NULL; } Py_XSETREF(obj2, NULL); assert(obj2 == NULL); // test Py_XSETREF() when the argument is NULL Py_XSETREF(obj2, NULL); assert(obj2 == NULL); // gh-98724: complex case, Py_SETREF() argument has a side effect PyObject* array[1]; array[0] = PyList_New(0); if (array[0] == NULL) { return NULL; } PyObject **p = array; Py_SETREF(*p++, NULL); assert(array[0] == NULL); assert(p == array + 1); // gh-98724: complex case, Py_XSETREF() argument has a side effect PyObject* array2[1]; array2[0] = PyList_New(0); if (array2[0] == NULL) { return NULL; } PyObject **p2 = array2; Py_XSETREF(*p2++, NULL); assert(array2[0] == NULL); assert(p2 == array2 + 1); // test Py_XSETREF() when the argument is NULL p2 = array2; Py_XSETREF(*p2++, NULL); assert(array2[0] == NULL); assert(p2 == array2 + 1); Py_RETURN_NONE; } #define TEST_REFCOUNT() \ do { \ PyObject *obj = PyList_New(0); \ if (obj == NULL) { \ return NULL; \ } \ assert(Py_REFCNT(obj) == 1); \ \ /* test Py_NewRef() */ \ PyObject *ref = Py_NewRef(obj); \ assert(ref == obj); \ assert(Py_REFCNT(obj) == 2); \ Py_DECREF(ref); \ \ /* test Py_XNewRef() */ \ PyObject *xref = Py_XNewRef(obj); \ assert(xref == obj); \ assert(Py_REFCNT(obj) == 2); \ Py_DECREF(xref); \ \ assert(Py_XNewRef(NULL) == NULL); \ \ Py_DECREF(obj); \ Py_RETURN_NONE; \ } while (0) \ // Test Py_NewRef() and Py_XNewRef() macros static PyObject* test_refcount_macros(PyObject *self, PyObject *Py_UNUSED(ignored)) { TEST_REFCOUNT(); } #undef Py_NewRef #undef Py_XNewRef // Test Py_NewRef() and Py_XNewRef() functions, after undefining macros. static PyObject* test_refcount_funcs(PyObject *self, PyObject *Py_UNUSED(ignored)) { TEST_REFCOUNT(); } // Test Py_Is() function #define TEST_PY_IS() \ do { \ PyObject *o_none = Py_None; \ PyObject *o_true = Py_True; \ PyObject *o_false = Py_False; \ PyObject *obj = PyList_New(0); \ if (obj == NULL) { \ return NULL; \ } \ \ /* test Py_Is() */ \ assert(Py_Is(obj, obj)); \ assert(!Py_Is(obj, o_none)); \ \ /* test Py_None */ \ assert(Py_Is(o_none, o_none)); \ assert(!Py_Is(obj, o_none)); \ \ /* test Py_True */ \ assert(Py_Is(o_true, o_true)); \ assert(!Py_Is(o_false, o_true)); \ assert(!Py_Is(obj, o_true)); \ \ /* test Py_False */ \ assert(Py_Is(o_false, o_false)); \ assert(!Py_Is(o_true, o_false)); \ assert(!Py_Is(obj, o_false)); \ \ Py_DECREF(obj); \ Py_RETURN_NONE; \ } while (0) // Test Py_Is() macro static PyObject* test_py_is_macros(PyObject *self, PyObject *Py_UNUSED(ignored)) { TEST_PY_IS(); } #undef Py_Is // Test Py_Is() function, after undefining its macro. static PyObject* test_py_is_funcs(PyObject *self, PyObject *Py_UNUSED(ignored)) { TEST_PY_IS(); } // type->tp_version_tag static PyObject * type_get_version(PyObject *self, PyObject *type) { if (!PyType_Check(type)) { PyErr_SetString(PyExc_TypeError, "argument must be a type"); return NULL; } PyObject *res = PyLong_FromUnsignedLong( ((PyTypeObject *)type)->tp_version_tag); if (res == NULL) { assert(PyErr_Occurred()); return NULL; } return res; } static PyObject * type_assign_version(PyObject *self, PyObject *type) { if (!PyType_Check(type)) { PyErr_SetString(PyExc_TypeError, "argument must be a type"); return NULL; } int res = PyUnstable_Type_AssignVersionTag((PyTypeObject *)type); return PyLong_FromLong(res); } // Test PyThreadState C API static PyObject * test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args)) { // PyThreadState_Get() PyThreadState *tstate = PyThreadState_Get(); assert(tstate != NULL); // PyThreadState_GET() PyThreadState *tstate2 = PyThreadState_Get(); assert(tstate2 == tstate); // private _PyThreadState_UncheckedGet() PyThreadState *tstate3 = _PyThreadState_UncheckedGet(); assert(tstate3 == tstate); // PyThreadState_EnterTracing(), PyThreadState_LeaveTracing() PyThreadState_EnterTracing(tstate); PyThreadState_LeaveTracing(tstate); // PyThreadState_GetDict(): no tstate argument PyObject *dict = PyThreadState_GetDict(); // PyThreadState_GetDict() API can return NULL if PyDict_New() fails, // but it should not occur in practice. assert(dict != NULL); assert(PyDict_Check(dict)); // dict is a borrowed reference // private _PyThreadState_GetDict() PyObject *dict2 = _PyThreadState_GetDict(tstate); assert(dict2 == dict); // dict2 is a borrowed reference // PyThreadState_GetInterpreter() PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate); assert(interp != NULL); // PyThreadState_GetFrame() PyFrameObject*frame = PyThreadState_GetFrame(tstate); assert(frame != NULL); assert(PyFrame_Check(frame)); Py_DECREF(frame); // PyThreadState_GetID() uint64_t id = PyThreadState_GetID(tstate); assert(id >= 1); Py_RETURN_NONE; } static PyObject * frame_getlocals(PyObject *self, PyObject *frame) { if (!PyFrame_Check(frame)) { PyErr_SetString(PyExc_TypeError, "argument must be a frame"); return NULL; } return PyFrame_GetLocals((PyFrameObject *)frame); } static PyObject * frame_getglobals(PyObject *self, PyObject *frame) { if (!PyFrame_Check(frame)) { PyErr_SetString(PyExc_TypeError, "argument must be a frame"); return NULL; } return PyFrame_GetGlobals((PyFrameObject *)frame); } static PyObject * frame_getgenerator(PyObject *self, PyObject *frame) { if (!PyFrame_Check(frame)) { PyErr_SetString(PyExc_TypeError, "argument must be a frame"); return NULL; } return PyFrame_GetGenerator((PyFrameObject *)frame); } static PyObject * frame_getbuiltins(PyObject *self, PyObject *frame) { if (!PyFrame_Check(frame)) { PyErr_SetString(PyExc_TypeError, "argument must be a frame"); return NULL; } return PyFrame_GetBuiltins((PyFrameObject *)frame); } static PyObject * frame_getlasti(PyObject *self, PyObject *frame) { if (!PyFrame_Check(frame)) { PyErr_SetString(PyExc_TypeError, "argument must be a frame"); return NULL; } int lasti = PyFrame_GetLasti((PyFrameObject *)frame); if (lasti < 0) { assert(lasti == -1); Py_RETURN_NONE; } return PyLong_FromLong(lasti); } static PyObject * frame_new(PyObject *self, PyObject *args) { PyObject *code, *globals, *locals; if (!PyArg_ParseTuple(args, "OOO", &code, &globals, &locals)) { return NULL; } if (!PyCode_Check(code)) { PyErr_SetString(PyExc_TypeError, "argument must be a code object"); return NULL; } PyThreadState *tstate = PyThreadState_Get(); return (PyObject *)PyFrame_New(tstate, (PyCodeObject *)code, globals, locals); } static PyObject * test_frame_getvar(PyObject *self, PyObject *args) { PyObject *frame, *name; if (!PyArg_ParseTuple(args, "OO", &frame, &name)) { return NULL; } if (!PyFrame_Check(frame)) { PyErr_SetString(PyExc_TypeError, "argument must be a frame"); return NULL; } return PyFrame_GetVar((PyFrameObject *)frame, name); } static PyObject * test_frame_getvarstring(PyObject *self, PyObject *args) { PyObject *frame; const char *name; if (!PyArg_ParseTuple(args, "Oy", &frame, &name)) { return NULL; } if (!PyFrame_Check(frame)) { PyErr_SetString(PyExc_TypeError, "argument must be a frame"); return NULL; } return PyFrame_GetVarString((PyFrameObject *)frame, name); } static PyObject * eval_get_func_name(PyObject *self, PyObject *func) { return PyUnicode_FromString(PyEval_GetFuncName(func)); } static PyObject * eval_get_func_desc(PyObject *self, PyObject *func) { return PyUnicode_FromString(PyEval_GetFuncDesc(func)); } static PyObject * gen_get_code(PyObject *self, PyObject *gen) { if (!PyGen_Check(gen)) { PyErr_SetString(PyExc_TypeError, "argument must be a generator object"); return NULL; } return (PyObject *)PyGen_GetCode((PyGenObject *)gen); } static PyObject * eval_eval_code_ex(PyObject *mod, PyObject *pos_args) { PyObject *result = NULL; PyObject *code; PyObject *globals; PyObject *locals = NULL; PyObject *args = NULL; PyObject *kwargs = NULL; PyObject *defaults = NULL; PyObject *kw_defaults = NULL; PyObject *closure = NULL; PyObject **c_kwargs = NULL; if (!PyArg_UnpackTuple(pos_args, "eval_code_ex", 2, 8, &code, &globals, &locals, &args, &kwargs, &defaults, &kw_defaults, &closure)) { goto exit; } if (!PyCode_Check(code)) { PyErr_SetString(PyExc_TypeError, "code must be a Python code object"); goto exit; } if (!PyDict_Check(globals)) { PyErr_SetString(PyExc_TypeError, "globals must be a dict"); goto exit; } if (locals && !PyMapping_Check(locals)) { PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); goto exit; } if (locals == Py_None) { locals = NULL; } PyObject **c_args = NULL; Py_ssize_t c_args_len = 0; if (args) { if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_TypeError, "args must be a tuple"); goto exit; } else { c_args = &PyTuple_GET_ITEM(args, 0); c_args_len = PyTuple_Size(args); } } Py_ssize_t c_kwargs_len = 0; if (kwargs) { if (!PyDict_Check(kwargs)) { PyErr_SetString(PyExc_TypeError, "keywords must be a dict"); goto exit; } else { c_kwargs_len = PyDict_Size(kwargs); if (c_kwargs_len > 0) { c_kwargs = PyMem_NEW(PyObject*, 2 * c_kwargs_len); if (!c_kwargs) { PyErr_NoMemory(); goto exit; } Py_ssize_t i = 0; Py_ssize_t pos = 0; while (PyDict_Next(kwargs, &pos, &c_kwargs[i], &c_kwargs[i + 1])) { i += 2; } c_kwargs_len = i / 2; /* XXX This is broken if the caller deletes dict items! */ } } } PyObject **c_defaults = NULL; Py_ssize_t c_defaults_len = 0; if (defaults && PyTuple_Check(defaults)) { c_defaults = &PyTuple_GET_ITEM(defaults, 0); c_defaults_len = PyTuple_Size(defaults); } if (kw_defaults && !PyDict_Check(kw_defaults)) { PyErr_SetString(PyExc_TypeError, "kw_defaults must be a dict"); goto exit; } if (closure && !PyTuple_Check(closure)) { PyErr_SetString(PyExc_TypeError, "closure must be a tuple of cells"); goto exit; } result = PyEval_EvalCodeEx( code, globals, locals, c_args, (int)c_args_len, c_kwargs, (int)c_kwargs_len, c_defaults, (int)c_defaults_len, kw_defaults, closure ); exit: if (c_kwargs) { PyMem_DEL(c_kwargs); } return result; } static PyObject * get_feature_macros(PyObject *self, PyObject *Py_UNUSED(args)) { PyObject *result = PyDict_New(); if (!result) { return NULL; } int res; #include "_testcapi_feature_macros.inc" return result; } static PyObject * test_code_api(PyObject *self, PyObject *Py_UNUSED(args)) { PyCodeObject *co = PyCode_NewEmpty("_testcapi", "dummy", 1); if (co == NULL) { return NULL; } /* co_code */ { PyObject *co_code = PyCode_GetCode(co); if (co_code == NULL) { goto fail; } assert(PyBytes_CheckExact(co_code)); if (PyObject_Length(co_code) == 0) { PyErr_SetString(PyExc_ValueError, "empty co_code"); Py_DECREF(co_code); goto fail; } Py_DECREF(co_code); } /* co_varnames */ { PyObject *co_varnames = PyCode_GetVarnames(co); if (co_varnames == NULL) { goto fail; } if (!PyTuple_CheckExact(co_varnames)) { PyErr_SetString(PyExc_TypeError, "co_varnames not tuple"); Py_DECREF(co_varnames); goto fail; } if (PyTuple_GET_SIZE(co_varnames) != 0) { PyErr_SetString(PyExc_ValueError, "non-empty co_varnames"); Py_DECREF(co_varnames); goto fail; } Py_DECREF(co_varnames); } /* co_cellvars */ { PyObject *co_cellvars = PyCode_GetCellvars(co); if (co_cellvars == NULL) { goto fail; } if (!PyTuple_CheckExact(co_cellvars)) { PyErr_SetString(PyExc_TypeError, "co_cellvars not tuple"); Py_DECREF(co_cellvars); goto fail; } if (PyTuple_GET_SIZE(co_cellvars) != 0) { PyErr_SetString(PyExc_ValueError, "non-empty co_cellvars"); Py_DECREF(co_cellvars); goto fail; } Py_DECREF(co_cellvars); } /* co_freevars */ { PyObject *co_freevars = PyCode_GetFreevars(co); if (co_freevars == NULL) { goto fail; } if (!PyTuple_CheckExact(co_freevars)) { PyErr_SetString(PyExc_TypeError, "co_freevars not tuple"); Py_DECREF(co_freevars); goto fail; } if (PyTuple_GET_SIZE(co_freevars) != 0) { PyErr_SetString(PyExc_ValueError, "non-empty co_freevars"); Py_DECREF(co_freevars); goto fail; } Py_DECREF(co_freevars); } Py_DECREF(co); Py_RETURN_NONE; fail: Py_DECREF(co); return NULL; } static int record_func(PyObject *obj, PyFrameObject *f, int what, PyObject *arg) { assert(PyList_Check(obj)); PyObject *what_obj = NULL; PyObject *line_obj = NULL; PyObject *tuple = NULL; int res = -1; what_obj = PyLong_FromLong(what); if (what_obj == NULL) { goto error; } int line = PyFrame_GetLineNumber(f); line_obj = PyLong_FromLong(line); if (line_obj == NULL) { goto error; } tuple = PyTuple_Pack(3, what_obj, line_obj, arg); if (tuple == NULL) { goto error; } PyTuple_SET_ITEM(tuple, 0, what_obj); if (PyList_Append(obj, tuple)) { goto error; } res = 0; error: Py_XDECREF(what_obj); Py_XDECREF(line_obj); Py_XDECREF(tuple); return res; } static PyObject * settrace_to_record(PyObject *self, PyObject *list) { if (!PyList_Check(list)) { PyErr_SetString(PyExc_TypeError, "argument must be a list"); return NULL; } PyEval_SetTrace(record_func, list); Py_RETURN_NONE; } static PyObject * clear_managed_dict(PyObject *self, PyObject *obj) { _PyObject_ClearManagedDict(obj); Py_RETURN_NONE; } static PyObject * test_macros(PyObject *self, PyObject *Py_UNUSED(args)) { struct MyStruct { int x; }; wchar_t array[3]; // static_assert(), Py_BUILD_ASSERT() static_assert(1 == 1, "bug"); Py_BUILD_ASSERT(1 == 1); // Py_MIN(), Py_MAX(), Py_ABS() assert(Py_MIN(5, 11) == 5); assert(Py_MAX(5, 11) == 11); assert(Py_ABS(-5) == 5); // Py_STRINGIFY() assert(strcmp(Py_STRINGIFY(123), "123") == 0); // Py_MEMBER_SIZE(), Py_ARRAY_LENGTH() assert(Py_MEMBER_SIZE(struct MyStruct, x) == sizeof(int)); assert(Py_ARRAY_LENGTH(array) == 3); // Py_CHARMASK() int c = 0xab00 | 7; assert(Py_CHARMASK(c) == 7); // _Py_IS_TYPE_SIGNED() assert(_Py_IS_TYPE_SIGNED(int)); assert(!_Py_IS_TYPE_SIGNED(unsigned int)); Py_RETURN_NONE; } static PyObject * function_get_code(PyObject *self, PyObject *func) { PyObject *code = PyFunction_GetCode(func); if (code != NULL) { return Py_NewRef(code); } else { return NULL; } } static PyObject * function_get_globals(PyObject *self, PyObject *func) { PyObject *globals = PyFunction_GetGlobals(func); if (globals != NULL) { return Py_NewRef(globals); } else { return NULL; } } static PyObject * function_get_module(PyObject *self, PyObject *func) { PyObject *module = PyFunction_GetModule(func); if (module != NULL) { return Py_NewRef(module); } else { return NULL; } } static PyObject * function_get_defaults(PyObject *self, PyObject *func) { PyObject *defaults = PyFunction_GetDefaults(func); if (defaults != NULL) { return Py_NewRef(defaults); } else if (PyErr_Occurred()) { return NULL; } else { Py_RETURN_NONE; // This can happen when `defaults` are set to `None` } } static PyObject * function_set_defaults(PyObject *self, PyObject *args) { PyObject *func = NULL, *defaults = NULL; if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) { return NULL; } int result = PyFunction_SetDefaults(func, defaults); if (result == -1) return NULL; Py_RETURN_NONE; } static PyObject * function_get_kw_defaults(PyObject *self, PyObject *func) { PyObject *defaults = PyFunction_GetKwDefaults(func); if (defaults != NULL) { return Py_NewRef(defaults); } else if (PyErr_Occurred()) { return NULL; } else { Py_RETURN_NONE; // This can happen when `kwdefaults` are set to `None` } } static PyObject * function_set_kw_defaults(PyObject *self, PyObject *args) { PyObject *func = NULL, *defaults = NULL; if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) { return NULL; } int result = PyFunction_SetKwDefaults(func, defaults); if (result == -1) return NULL; Py_RETURN_NONE; } struct gc_visit_state_basic { PyObject *target; int found; }; static int gc_visit_callback_basic(PyObject *obj, void *arg) { struct gc_visit_state_basic *state = (struct gc_visit_state_basic *)arg; if (obj == state->target) { state->found = 1; return 0; } return 1; } static PyObject * test_gc_visit_objects_basic(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) { PyObject *obj; struct gc_visit_state_basic state; obj = PyList_New(0); if (obj == NULL) { return NULL; } state.target = obj; state.found = 0; PyUnstable_GC_VisitObjects(gc_visit_callback_basic, &state); Py_DECREF(obj); if (!state.found) { PyErr_SetString( PyExc_AssertionError, "test_gc_visit_objects_basic: Didn't find live list"); return NULL; } Py_RETURN_NONE; } static int gc_visit_callback_exit_early(PyObject *obj, void *arg) { int *visited_i = (int *)arg; (*visited_i)++; if (*visited_i == 2) { return 0; } return 1; } static PyObject * test_gc_visit_objects_exit_early(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) { int visited_i = 0; PyUnstable_GC_VisitObjects(gc_visit_callback_exit_early, &visited_i); if (visited_i != 2) { PyErr_SetString( PyExc_AssertionError, "test_gc_visit_objects_exit_early: did not exit when expected"); } Py_RETURN_NONE; } struct atexit_data { int called; }; static void callback(void *data) { ((struct atexit_data *)data)->called += 1; } static PyObject * test_atexit(PyObject *self, PyObject *Py_UNUSED(args)) { PyThreadState *oldts = PyThreadState_Swap(NULL); PyThreadState *tstate = Py_NewInterpreter(); struct atexit_data data = {0}; int res = _Py_AtExit(tstate->interp, callback, (void *)&data); Py_EndInterpreter(tstate); PyThreadState_Swap(oldts); if (res < 0) { return NULL; } if (data.called == 0) { PyErr_SetString(PyExc_RuntimeError, "atexit callback not called"); return NULL; } Py_RETURN_NONE; } static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyMethodDef TestMethods[] = { {"set_errno", set_errno, METH_VARARGS}, {"test_config", test_config, METH_NOARGS}, {"test_sizeof_c_types", test_sizeof_c_types, METH_NOARGS}, {"test_gc_control", test_gc_control, METH_NOARGS}, {"test_list_api", test_list_api, METH_NOARGS}, {"test_dict_iteration", test_dict_iteration, METH_NOARGS}, {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS}, {"test_lazy_hash_inheritance", test_lazy_hash_inheritance,METH_NOARGS}, {"test_xincref_doesnt_leak",test_xincref_doesnt_leak, METH_NOARGS}, {"test_incref_doesnt_leak", test_incref_doesnt_leak, METH_NOARGS}, {"test_xdecref_doesnt_leak",test_xdecref_doesnt_leak, METH_NOARGS}, {"test_decref_doesnt_leak", test_decref_doesnt_leak, METH_NOARGS}, {"test_structseq_newtype_doesnt_leak", test_structseq_newtype_doesnt_leak, METH_NOARGS}, {"test_structseq_newtype_null_descr_doc", test_structseq_newtype_null_descr_doc, METH_NOARGS}, {"test_incref_decref_API", test_incref_decref_API, METH_NOARGS}, {"pyobject_repr_from_null", pyobject_repr_from_null, METH_NOARGS}, {"pyobject_str_from_null", pyobject_str_from_null, METH_NOARGS}, {"pyobject_bytes_from_null", pyobject_bytes_from_null, METH_NOARGS}, {"test_string_to_double", test_string_to_double, METH_NOARGS}, {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS}, {"test_from_contiguous", (PyCFunction)test_from_contiguous, METH_NOARGS}, #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__) {"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS}, #endif {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O}, {"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS}, {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, {"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS}, {"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS}, {"test_get_type_name", test_get_type_name, METH_NOARGS}, {"test_get_type_qualname", test_get_type_qualname, METH_NOARGS}, {"_test_thread_state", test_thread_state, METH_VARARGS}, #ifndef MS_WINDOWS {"_spawn_pthread_waiter", spawn_pthread_waiter, METH_NOARGS}, {"_end_spawned_pthread", end_spawned_pthread, METH_NOARGS}, #endif {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, #ifdef HAVE_GETTIMEOFDAY {"profile_int", profile_int, METH_NOARGS}, #endif {"argparsing", argparsing, METH_VARARGS}, {"code_newempty", code_newempty, METH_VARARGS}, {"eval_code_ex", eval_eval_code_ex, METH_VARARGS}, {"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer, METH_NOARGS}, {"crash_no_current_thread", crash_no_current_thread, METH_NOARGS}, {"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS}, {"run_in_subinterp", run_in_subinterp, METH_VARARGS}, {"run_in_subinterp_with_config", _PyCFunction_CAST(run_in_subinterp_with_config), METH_VARARGS | METH_KEYWORDS}, {"get_crossinterp_data", get_crossinterp_data, METH_VARARGS}, {"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS}, {"with_tp_del", with_tp_del, METH_VARARGS}, {"create_cfunction", create_cfunction, METH_NOARGS}, {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS, PyDoc_STR("set_error_class(error_class) -> None")}, {"join_temporary_c_thread", join_temporary_c_thread, METH_NOARGS}, {"pymarshal_write_long_to_file", pymarshal_write_long_to_file, METH_VARARGS}, {"pymarshal_write_object_to_file", pymarshal_write_object_to_file, METH_VARARGS}, {"pymarshal_read_short_from_file", pymarshal_read_short_from_file, METH_VARARGS}, {"pymarshal_read_long_from_file", pymarshal_read_long_from_file, METH_VARARGS}, {"pymarshal_read_last_object_from_file", pymarshal_read_last_object_from_file, METH_VARARGS}, {"pymarshal_read_object_from_file", pymarshal_read_object_from_file, METH_VARARGS}, {"return_null_without_error", return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, {"getitem_with_error", getitem_with_error, METH_VARARGS}, {"Py_CompileString", pycompilestring, METH_O}, {"dict_get_version", dict_get_version, METH_VARARGS}, {"raise_SIGINT_then_send_None", raise_SIGINT_then_send_None, METH_VARARGS}, {"stack_pointer", stack_pointer, METH_NOARGS}, #ifdef W_STOPCODE {"W_STOPCODE", py_w_stopcode, METH_VARARGS}, #endif {"get_mapping_keys", get_mapping_keys, METH_O}, {"get_mapping_values", get_mapping_values, METH_O}, {"get_mapping_items", get_mapping_items, METH_O}, {"test_mapping_has_key_string", test_mapping_has_key_string, METH_NOARGS}, {"mapping_has_key", mapping_has_key, METH_VARARGS}, {"sequence_set_slice", sequence_set_slice, METH_VARARGS}, {"sequence_del_slice", sequence_del_slice, METH_VARARGS}, {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS}, {"hamt", new_hamt, METH_NOARGS}, {"bad_get", _PyCFunction_CAST(bad_get), METH_FASTCALL}, #ifdef Py_REF_DEBUG {"negative_refcount", negative_refcount, METH_NOARGS}, #endif {"sequence_getitem", sequence_getitem, METH_VARARGS}, {"sequence_setitem", sequence_setitem, METH_VARARGS}, {"sequence_delitem", sequence_delitem, METH_VARARGS}, {"hasattr_string", hasattr_string, METH_VARARGS}, {"meth_varargs", meth_varargs, METH_VARARGS}, {"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS}, {"meth_o", meth_o, METH_O}, {"meth_noargs", meth_noargs, METH_NOARGS}, {"meth_fastcall", _PyCFunction_CAST(meth_fastcall), METH_FASTCALL}, {"meth_fastcall_keywords", _PyCFunction_CAST(meth_fastcall_keywords), METH_FASTCALL|METH_KEYWORDS}, {"pynumber_tobase", pynumber_tobase, METH_VARARGS}, {"without_gc", without_gc, METH_O}, {"test_set_type_size", test_set_type_size, METH_NOARGS}, {"test_py_clear", test_py_clear, METH_NOARGS}, {"test_py_setref", test_py_setref, METH_NOARGS}, {"test_refcount_macros", test_refcount_macros, METH_NOARGS}, {"test_refcount_funcs", test_refcount_funcs, METH_NOARGS}, {"test_py_is_macros", test_py_is_macros, METH_NOARGS}, {"test_py_is_funcs", test_py_is_funcs, METH_NOARGS}, {"type_get_version", type_get_version, METH_O, PyDoc_STR("type->tp_version_tag")}, {"type_assign_version", type_assign_version, METH_O, PyDoc_STR("PyUnstable_Type_AssignVersionTag")}, {"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL}, {"frame_getlocals", frame_getlocals, METH_O, NULL}, {"frame_getglobals", frame_getglobals, METH_O, NULL}, {"frame_getgenerator", frame_getgenerator, METH_O, NULL}, {"frame_getbuiltins", frame_getbuiltins, METH_O, NULL}, {"frame_getlasti", frame_getlasti, METH_O, NULL}, {"frame_new", frame_new, METH_VARARGS, NULL}, {"frame_getvar", test_frame_getvar, METH_VARARGS, NULL}, {"frame_getvarstring", test_frame_getvarstring, METH_VARARGS, NULL}, {"eval_get_func_name", eval_get_func_name, METH_O, NULL}, {"eval_get_func_desc", eval_get_func_desc, METH_O, NULL}, {"gen_get_code", gen_get_code, METH_O, NULL}, {"get_feature_macros", get_feature_macros, METH_NOARGS, NULL}, {"test_code_api", test_code_api, METH_NOARGS, NULL}, {"settrace_to_record", settrace_to_record, METH_O, NULL}, {"test_macros", test_macros, METH_NOARGS, NULL}, {"clear_managed_dict", clear_managed_dict, METH_O, NULL}, {"function_get_code", function_get_code, METH_O, NULL}, {"function_get_globals", function_get_globals, METH_O, NULL}, {"function_get_module", function_get_module, METH_O, NULL}, {"function_get_defaults", function_get_defaults, METH_O, NULL}, {"function_set_defaults", function_set_defaults, METH_VARARGS, NULL}, {"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL}, {"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL}, {"test_gc_visit_objects_basic", test_gc_visit_objects_basic, METH_NOARGS, NULL}, {"test_gc_visit_objects_exit_early", test_gc_visit_objects_exit_early, METH_NOARGS, NULL}, {"test_atexit", test_atexit, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; 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_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 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 */ }; typedef struct { PyObject_HEAD } ipowObject; static PyObject * ipowType_ipow(PyObject *self, PyObject *other, PyObject *mod) { return Py_BuildValue("OO", other, mod); } static PyNumberMethods ipowType_as_number = { .nb_inplace_power = ipowType_ipow }; static PyTypeObject ipowType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "ipowType", .tp_basicsize = sizeof(ipowObject), .tp_as_number = &ipowType_as_number, .tp_new = PyType_GenericNew }; typedef struct { PyObject_HEAD PyObject *ao_iterator; } awaitObject; static PyObject * awaitObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *v; awaitObject *ao; if (!PyArg_UnpackTuple(args, "awaitObject", 1, 1, &v)) return NULL; ao = (awaitObject *)type->tp_alloc(type, 0); if (ao == NULL) { return NULL; } ao->ao_iterator = Py_NewRef(v); return (PyObject *)ao; } static void awaitObject_dealloc(awaitObject *ao) { Py_CLEAR(ao->ao_iterator); Py_TYPE(ao)->tp_free(ao); } static PyObject * awaitObject_await(awaitObject *ao) { return Py_NewRef(ao->ao_iterator); } static PyAsyncMethods awaitType_as_async = { (unaryfunc)awaitObject_await, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ 0, /* am_send */ }; static PyTypeObject awaitType = { PyVarObject_HEAD_INIT(NULL, 0) "awaitType", sizeof(awaitObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)awaitObject_dealloc, /* destructor tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ &awaitType_as_async, /* tp_as_async */ 0, /* tp_repr */ 0, /* 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 tp_as_async", 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, awaitObject_new, /* tp_new */ PyObject_Del, /* tp_free */ }; /* Test bpo-35983: create a subclass of "list" which checks that instances * are not deallocated twice */ typedef struct { PyListObject list; int deallocated; } MyListObject; static PyObject * MyList_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject* op = PyList_Type.tp_new(type, args, kwds); ((MyListObject*)op)->deallocated = 0; return op; } void MyList_dealloc(MyListObject* op) { if (op->deallocated) { /* We cannot raise exceptions here but we still want the testsuite * to fail when we hit this */ Py_FatalError("MyList instance deallocated twice"); } op->deallocated = 1; PyList_Type.tp_dealloc((PyObject *)op); } static PyTypeObject MyList_Type = { PyVarObject_HEAD_INIT(NULL, 0) "MyList", sizeof(MyListObject), 0, (destructor)MyList_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* &PyList_Type */ /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MyList_new, /* tp_new */ }; /* Test PEP 560 */ typedef struct { PyObject_HEAD PyObject *item; } PyGenericAliasObject; static void generic_alias_dealloc(PyGenericAliasObject *self) { Py_CLEAR(self->item); Py_TYPE(self)->tp_free((PyObject *)self); } static PyObject * generic_alias_mro_entries(PyGenericAliasObject *self, PyObject *bases) { return PyTuple_Pack(1, self->item); } static PyMethodDef generic_alias_methods[] = { {"__mro_entries__", _PyCFunction_CAST(generic_alias_mro_entries), METH_O, NULL}, {NULL} /* sentinel */ }; static PyTypeObject GenericAlias_Type = { PyVarObject_HEAD_INIT(NULL, 0) "GenericAlias", sizeof(PyGenericAliasObject), 0, .tp_dealloc = (destructor)generic_alias_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_methods = generic_alias_methods, }; static PyObject * generic_alias_new(PyObject *item) { PyGenericAliasObject *o = PyObject_New(PyGenericAliasObject, &GenericAlias_Type); if (o == NULL) { return NULL; } o->item = Py_NewRef(item); return (PyObject*) o; } typedef struct { PyObject_HEAD } PyGenericObject; static PyObject * generic_class_getitem(PyObject *type, PyObject *item) { return generic_alias_new(item); } static PyMethodDef generic_methods[] = { {"__class_getitem__", generic_class_getitem, METH_O|METH_CLASS, NULL}, {NULL} /* sentinel */ }; static PyTypeObject Generic_Type = { PyVarObject_HEAD_INIT(NULL, 0) "Generic", sizeof(PyGenericObject), 0, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_methods = generic_methods, }; static PyMethodDef meth_instance_methods[] = { {"meth_varargs", meth_varargs, METH_VARARGS}, {"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS}, {"meth_o", meth_o, METH_O}, {"meth_noargs", meth_noargs, METH_NOARGS}, {"meth_fastcall", _PyCFunction_CAST(meth_fastcall), METH_FASTCALL}, {"meth_fastcall_keywords", _PyCFunction_CAST(meth_fastcall_keywords), METH_FASTCALL|METH_KEYWORDS}, {NULL, NULL} /* sentinel */ }; static PyTypeObject MethInstance_Type = { PyVarObject_HEAD_INIT(NULL, 0) "MethInstance", sizeof(PyObject), .tp_new = PyType_GenericNew, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_methods = meth_instance_methods, .tp_doc = (char*)PyDoc_STR( "Class with normal (instance) methods to test calling conventions"), }; static PyMethodDef meth_class_methods[] = { {"meth_varargs", meth_varargs, METH_VARARGS|METH_CLASS}, {"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS|METH_CLASS}, {"meth_o", meth_o, METH_O|METH_CLASS}, {"meth_noargs", meth_noargs, METH_NOARGS|METH_CLASS}, {"meth_fastcall", _PyCFunction_CAST(meth_fastcall), METH_FASTCALL|METH_CLASS}, {"meth_fastcall_keywords", _PyCFunction_CAST(meth_fastcall_keywords), METH_FASTCALL|METH_KEYWORDS|METH_CLASS}, {NULL, NULL} /* sentinel */ }; static PyTypeObject MethClass_Type = { PyVarObject_HEAD_INIT(NULL, 0) "MethClass", sizeof(PyObject), .tp_new = PyType_GenericNew, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_methods = meth_class_methods, .tp_doc = PyDoc_STR( "Class with class methods to test calling conventions"), }; static PyMethodDef meth_static_methods[] = { {"meth_varargs", meth_varargs, METH_VARARGS|METH_STATIC}, {"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS|METH_STATIC}, {"meth_o", meth_o, METH_O|METH_STATIC}, {"meth_noargs", meth_noargs, METH_NOARGS|METH_STATIC}, {"meth_fastcall", _PyCFunction_CAST(meth_fastcall), METH_FASTCALL|METH_STATIC}, {"meth_fastcall_keywords", _PyCFunction_CAST(meth_fastcall_keywords), METH_FASTCALL|METH_KEYWORDS|METH_STATIC}, {NULL, NULL} /* sentinel */ }; static PyTypeObject MethStatic_Type = { PyVarObject_HEAD_INIT(NULL, 0) "MethStatic", sizeof(PyObject), .tp_new = PyType_GenericNew, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_methods = meth_static_methods, .tp_doc = PyDoc_STR( "Class with static methods to test calling conventions"), }; /* ContainerNoGC -- a simple container without GC methods */ typedef struct { PyObject_HEAD PyObject *value; } ContainerNoGCobject; static PyObject * ContainerNoGC_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *value; char *names[] = {"value", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", names, &value)) { return NULL; } PyObject *self = type->tp_alloc(type, 0); if (self == NULL) { return NULL; } Py_INCREF(value); ((ContainerNoGCobject *)self)->value = value; return self; } static void ContainerNoGC_dealloc(ContainerNoGCobject *self) { Py_DECREF(self->value); Py_TYPE(self)->tp_free((PyObject *)self); } static PyMemberDef ContainerNoGC_members[] = { {"value", T_OBJECT, offsetof(ContainerNoGCobject, value), READONLY, PyDoc_STR("a container value for test purposes")}, {0} }; static PyTypeObject ContainerNoGC_type = { PyVarObject_HEAD_INIT(NULL, 0) "_testcapi.ContainerNoGC", sizeof(ContainerNoGCobject), .tp_dealloc = (destructor)ContainerNoGC_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_members = ContainerNoGC_members, .tp_new = ContainerNoGC_new, }; static struct PyModuleDef _testcapimodule = { PyModuleDef_HEAD_INIT, "_testcapi", NULL, -1, TestMethods, NULL, NULL, NULL, NULL }; /* Per PEP 489, this module will not be converted to multi-phase initialization */ PyMODINIT_FUNC PyInit__testcapi(void) { PyObject *m; m = PyModule_Create(&_testcapimodule); if (m == NULL) return NULL; Py_SET_TYPE(&_HashInheritanceTester_Type, &PyType_Type); if (PyType_Ready(&matmulType) < 0) return NULL; Py_INCREF(&matmulType); PyModule_AddObject(m, "matmulType", (PyObject *)&matmulType); if (PyType_Ready(&ipowType) < 0) { return NULL; } Py_INCREF(&ipowType); PyModule_AddObject(m, "ipowType", (PyObject *)&ipowType); if (PyType_Ready(&awaitType) < 0) return NULL; Py_INCREF(&awaitType); PyModule_AddObject(m, "awaitType", (PyObject *)&awaitType); MyList_Type.tp_base = &PyList_Type; if (PyType_Ready(&MyList_Type) < 0) return NULL; Py_INCREF(&MyList_Type); PyModule_AddObject(m, "MyList", (PyObject *)&MyList_Type); if (PyType_Ready(&GenericAlias_Type) < 0) return NULL; Py_INCREF(&GenericAlias_Type); PyModule_AddObject(m, "GenericAlias", (PyObject *)&GenericAlias_Type); if (PyType_Ready(&Generic_Type) < 0) return NULL; Py_INCREF(&Generic_Type); PyModule_AddObject(m, "Generic", (PyObject *)&Generic_Type); if (PyType_Ready(&MethInstance_Type) < 0) return NULL; Py_INCREF(&MethInstance_Type); PyModule_AddObject(m, "MethInstance", (PyObject *)&MethInstance_Type); if (PyType_Ready(&MethClass_Type) < 0) return NULL; Py_INCREF(&MethClass_Type); PyModule_AddObject(m, "MethClass", (PyObject *)&MethClass_Type); if (PyType_Ready(&MethStatic_Type) < 0) return NULL; Py_INCREF(&MethStatic_Type); PyModule_AddObject(m, "MethStatic", (PyObject *)&MethStatic_Type); PyModule_AddObject(m, "CHAR_MAX", PyLong_FromLong(CHAR_MAX)); PyModule_AddObject(m, "CHAR_MIN", PyLong_FromLong(CHAR_MIN)); PyModule_AddObject(m, "UCHAR_MAX", PyLong_FromLong(UCHAR_MAX)); PyModule_AddObject(m, "SHRT_MAX", PyLong_FromLong(SHRT_MAX)); PyModule_AddObject(m, "SHRT_MIN", PyLong_FromLong(SHRT_MIN)); PyModule_AddObject(m, "USHRT_MAX", PyLong_FromLong(USHRT_MAX)); PyModule_AddObject(m, "INT_MAX", PyLong_FromLong(INT_MAX)); PyModule_AddObject(m, "INT_MIN", PyLong_FromLong(INT_MIN)); PyModule_AddObject(m, "UINT_MAX", PyLong_FromUnsignedLong(UINT_MAX)); PyModule_AddObject(m, "LONG_MAX", PyLong_FromLong(LONG_MAX)); PyModule_AddObject(m, "LONG_MIN", PyLong_FromLong(LONG_MIN)); PyModule_AddObject(m, "ULONG_MAX", PyLong_FromUnsignedLong(ULONG_MAX)); PyModule_AddObject(m, "FLT_MAX", PyFloat_FromDouble(FLT_MAX)); PyModule_AddObject(m, "FLT_MIN", PyFloat_FromDouble(FLT_MIN)); PyModule_AddObject(m, "DBL_MAX", PyFloat_FromDouble(DBL_MAX)); PyModule_AddObject(m, "DBL_MIN", PyFloat_FromDouble(DBL_MIN)); PyModule_AddObject(m, "LLONG_MAX", PyLong_FromLongLong(LLONG_MAX)); PyModule_AddObject(m, "LLONG_MIN", PyLong_FromLongLong(LLONG_MIN)); PyModule_AddObject(m, "ULLONG_MAX", PyLong_FromUnsignedLongLong(ULLONG_MAX)); 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_TIME_T", PyLong_FromSsize_t(sizeof(time_t))); PyModule_AddObject(m, "Py_Version", PyLong_FromUnsignedLong(Py_Version)); Py_INCREF(&PyInstanceMethod_Type); PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type); PyModule_AddIntConstant(m, "the_number_three", 3); TestError = PyErr_NewException("_testcapi.error", NULL, NULL); Py_INCREF(TestError); PyModule_AddObject(m, "error", TestError); if (PyType_Ready(&ContainerNoGC_type) < 0) { return NULL; } Py_INCREF(&ContainerNoGC_type); if (PyModule_AddObject(m, "ContainerNoGC", (PyObject *) &ContainerNoGC_type) < 0) return NULL; /* Include tests from the _testcapi/ directory */ if (_PyTestCapi_Init_Vectorcall(m) < 0) { return NULL; } if (_PyTestCapi_Init_Heaptype(m) < 0) { return NULL; } if (_PyTestCapi_Init_Unicode(m) < 0) { return NULL; } if (_PyTestCapi_Init_GetArgs(m) < 0) { return NULL; } if (_PyTestCapi_Init_PyTime(m) < 0) { return NULL; } if (_PyTestCapi_Init_DateTime(m) < 0) { return NULL; } if (_PyTestCapi_Init_Docstring(m) < 0) { return NULL; } if (_PyTestCapi_Init_Mem(m) < 0) { return NULL; } if (_PyTestCapi_Init_Watchers(m) < 0) { return NULL; } if (_PyTestCapi_Init_Long(m) < 0) { return NULL; } if (_PyTestCapi_Init_Float(m) < 0) { return NULL; } if (_PyTestCapi_Init_Structmember(m) < 0) { return NULL; } if (_PyTestCapi_Init_Exceptions(m) < 0) { return NULL; } if (_PyTestCapi_Init_Code(m) < 0) { return NULL; } if (_PyTestCapi_Init_PyOS(m) < 0) { return NULL; } #ifndef LIMITED_API_AVAILABLE PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False); #else PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_True); if (_PyTestCapi_Init_VectorcallLimited(m) < 0) { return NULL; } #endif PyState_AddModule(m, &_testcapimodule); return m; } /* Test the C API exposed when PY_SSIZE_T_CLEAN is not defined */ #undef Py_BuildValue PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...); static PyObject * test_buildvalue_issue38913(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyObject *res; const char str[] = "string"; const Py_UNICODE unicode[] = L"unicode"; assert(!PyErr_Occurred()); res = Py_BuildValue("(s#O)", str, 1, Py_None); assert(res == NULL); if (!PyErr_ExceptionMatches(PyExc_SystemError)) { return NULL; } PyErr_Clear(); res = Py_BuildValue("(z#O)", str, 1, Py_None); assert(res == NULL); if (!PyErr_ExceptionMatches(PyExc_SystemError)) { return NULL; } PyErr_Clear(); res = Py_BuildValue("(y#O)", str, 1, Py_None); assert(res == NULL); if (!PyErr_ExceptionMatches(PyExc_SystemError)) { return NULL; } PyErr_Clear(); res = Py_BuildValue("(u#O)", unicode, 1, Py_None); assert(res == NULL); if (!PyErr_ExceptionMatches(PyExc_SystemError)) { return NULL; } PyErr_Clear(); Py_RETURN_NONE; }