/* Generic object operations; and implementation of None */
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_context.h" // _PyContextTokenMissing_Type
#include "pycore_descrobject.h" // _PyMethodWrapper_Type
#include "pycore_dict.h" // _PyObject_MakeDictFromInstanceAttributes()
#include "pycore_floatobject.h" // _PyFloat_DebugMallocStats()
#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
#include "pycore_hashtable.h" // _Py_hashtable_new()
#include "pycore_memoryobject.h" // _PyManagedBuffer_Type
#include "pycore_namespace.h" // _PyNamespace_Type
#include "pycore_object.h" // PyAPI_DATA() _Py_SwappedOp definition
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_symtable.h" // PySTEntry_Type
#include "pycore_typeobject.h" // _PyBufferWrapper_Type
#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic
#include "pycore_unionobject.h" // _PyUnion_Type
#include "interpreteridobject.h" // _PyInterpreterID_Type
#ifdef Py_LIMITED_API
// Prevent recursive call _Py_IncRef() <=> Py_INCREF()
# error "Py_LIMITED_API macro must not be defined"
#endif
/* Defined in tracemalloc.c */
extern void _PyMem_DumpTraceback(int fd, const void *ptr);
int
_PyObject_CheckConsistency(PyObject *op, int check_content)
{
#define CHECK(expr) \
do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0)
CHECK(!_PyObject_IsFreed(op));
CHECK(Py_REFCNT(op) >= 1);
_PyType_CheckConsistency(Py_TYPE(op));
if (PyUnicode_Check(op)) {
_PyUnicode_CheckConsistency(op, check_content);
}
else if (PyDict_Check(op)) {
_PyDict_CheckConsistency(op, check_content);
}
return 1;
#undef CHECK
}
#ifdef Py_REF_DEBUG
/* We keep the legacy symbol around for backward compatibility. */
Py_ssize_t _Py_RefTotal;
static inline Py_ssize_t
get_legacy_reftotal(void)
{
return _Py_RefTotal;
}
#endif
#ifdef Py_REF_DEBUG
# define REFTOTAL(interp) \
interp->object_state.reftotal
static inline void
reftotal_increment(PyInterpreterState *interp)
{
REFTOTAL(interp)++;
}
static inline void
reftotal_decrement(PyInterpreterState *interp)
{
REFTOTAL(interp)--;
}
static inline void
reftotal_add(PyInterpreterState *interp, Py_ssize_t n)
{
REFTOTAL(interp) += n;
}
static inline Py_ssize_t get_global_reftotal(_PyRuntimeState *);
/* We preserve the number of refs leaked during runtime finalization,
so they can be reported if the runtime is initialized again. */
// XXX We don't lose any information by dropping this,
// so we should consider doing so.
static Py_ssize_t last_final_reftotal = 0;
void
_Py_FinalizeRefTotal(_PyRuntimeState *runtime)
{
last_final_reftotal = get_global_reftotal(runtime);
runtime->object_state.interpreter_leaks = 0;
}
void
_PyInterpreterState_FinalizeRefTotal(PyInterpreterState *interp)
{
interp->runtime->object_state.interpreter_leaks += REFTOTAL(interp);
REFTOTAL(interp) = 0;
}
static inline Py_ssize_t
get_reftotal(PyInterpreterState *interp)
{
/* For a single interpreter, we ignore the legacy _Py_RefTotal,
since we can't determine which interpreter updated it. */
return REFTOTAL(interp);
}
static inline Py_ssize_t
get_global_reftotal(_PyRuntimeState *runtime)
{
Py_ssize_t total = 0;
/* Add up the total from each interpreter. */
HEAD_LOCK(&_PyRuntime);
PyInterpreterState *interp = PyInterpreterState_Head();
for (; interp != NULL; interp = PyInterpreterState_Next(interp)) {
total += REFTOTAL(interp);
}
HEAD_UNLOCK(&_PyRuntime);
/* Add in the updated value from the legacy _Py_RefTotal. */
total += get_legacy_reftotal();
total += last_final_reftotal;
total += runtime->object_state.interpreter_leaks;
return total;
}
#undef REFTOTAL
void
_PyDebug_PrintTotalRefs(void) {
_PyRuntimeState *runtime = &_PyRuntime;
fprintf(stderr,
"[%zd refs, %zd blocks]\n",
get_global_reftotal(runtime), _Py_GetGlobalAllocatedBlocks());
/* It may be helpful to also print the "legacy" reftotal separately.
Likewise for the total for each interpreter. */
}
#endif /* Py_REF_DEBUG */
/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
These are used by the individual routines for object creation.
Do not call them otherwise, they do not initialize the object! */
#ifdef Py_TRACE_REFS
#define REFCHAIN(interp) interp->object_state.refchain
#define REFCHAIN_VALUE ((void*)(uintptr_t)1)
bool
_PyRefchain_IsTraced(PyInterpreterState *interp, PyObject *obj)
{
return (_Py_hashtable_get(REFCHAIN(interp), obj) == REFCHAIN_VALUE);
}
static void
_PyRefchain_Trace(PyInterpreterState *interp, PyObject *obj)
{
if (_Py_hashtable_set(REFCHAIN(interp), obj, REFCHAIN_VALUE) < 0) {
// Use a fatal error because _Py_NewReference() cannot report
// the error to the caller.
Py_FatalError("_Py_hashtable_set() memory allocation failed");
}
}
static void
_PyRefchain_Remove(PyInterpreterState *interp, PyObject *obj)
{
void *value = _Py_hashtable_steal(REFCHAIN(interp), obj);
#ifndef NDEBUG
assert(value == REFCHAIN_VALUE);
#else
(void)value;
#endif
}
/* Add an object to the refchain hash table.
*
* Note that objects are normally added to the list by PyObject_Init()
* indirectly. Not all objects are initialized that way, though; exceptions
* include statically allocated type objects, and statically allocated
* singletons (like Py_True and Py_None). */
void
_Py_AddToAllObjects(PyObject *op)
{
PyInterpreterState *interp = _PyInterpreterState_GET();
if (!_PyRefchain_IsTraced(interp, op)) {
_PyRefchain_Trace(interp, op);
}
}
#endif /* Py_TRACE_REFS */
#ifdef Py_REF_DEBUG
/* Log a fatal error; doesn't return. */
void
_Py_NegativeRefcount(const char *filename, int lineno, PyObject *op)
{
_PyObject_AssertFailed(op, NULL, "object has negative ref count",
filename, lineno, __func__);
}
/* This is used strictly by Py_INCREF(). */
void
_Py_INCREF_IncRefTotal(void)
{
reftotal_increment(_PyInterpreterState_GET());
}
/* This is used strictly by Py_DECREF(). */
void
_Py_DECREF_DecRefTotal(void)
{
reftotal_decrement(_PyInterpreterState_GET());
}
void
_Py_IncRefTotal(PyInterpreterState *interp)
{
reftotal_increment(interp);
}
void
_Py_DecRefTotal(PyInterpreterState *interp)
{
reftotal_decrement(interp);
}
void
_Py_AddRefTotal(PyInterpreterState *interp, Py_ssize_t n)
{
reftotal_add(interp, n);
}
/* This includes the legacy total
and any carried over from the last runtime init/fini cycle. */
Py_ssize_t
_Py_GetGlobalRefTotal(void)
{
return get_global_reftotal(&_PyRuntime);
}
Py_ssize_t
_Py_GetLegacyRefTotal(void)
{
return get_legacy_reftotal();
}
Py_ssize_t
_PyInterpreterState_GetRefTotal(PyInterpreterState *interp)
{
return get_reftotal(interp);
}
#endif /* Py_REF_DEBUG */
void
Py_IncRef(PyObject *o)
{
Py_XINCREF(o);
}
void
Py_DecRef(PyObject *o)
{
Py_XDECREF(o);
}
void
_Py_IncRef(PyObject *o)
{
Py_INCREF(o);
}
void
_Py_DecRef(PyObject *o)
{
Py_DECREF(o);
}
/**************************************/
PyObject *
PyObject_Init(PyObject *op, PyTypeObject *tp)
{
if (op == NULL) {
return PyErr_NoMemory();
}
_PyObject_Init(op, tp);
return op;
}
PyVarObject *
PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
{
if (op == NULL) {
return (PyVarObject *) PyErr_NoMemory();
}
_PyObject_InitVar(op, tp, size);
return op;
}
PyObject *
_PyObject_New(PyTypeObject *tp)
{
PyObject *op = (PyObject *) PyObject_Malloc(_PyObject_SIZE(tp));
if (op == NULL) {
return PyErr_NoMemory();
}
_PyObject_Init(op, tp);
return op;
}
PyVarObject *
_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
{
PyVarObject *op;
const size_t size = _PyObject_VAR_SIZE(tp, nitems);
op = (PyVarObject *) PyObject_Malloc(size);
if (op == NULL) {
return (PyVarObject *)PyErr_NoMemory();
}
_PyObject_InitVar(op, tp, nitems);
return op;
}
void
PyObject_CallFinalizer(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
if (tp->tp_finalize == NULL)
return;
/* tp_finalize should only be called once. */
if (_PyType_IS_GC(tp) && _PyGC_FINALIZED(self))
return;
tp->tp_finalize(self);
if (_PyType_IS_GC(tp)) {
_PyGC_SET_FINALIZED(self);
}
}
int
PyObject_CallFinalizerFromDealloc(PyObject *self)
{
if (Py_REFCNT(self) != 0) {
_PyObject_ASSERT_FAILED_MSG(self,
"PyObject_CallFinalizerFromDealloc called "
"on object with a non-zero refcount");
}
/* Temporarily resurrect the object. */
Py_SET_REFCNT(self, 1);
PyObject_CallFinalizer(self);
_PyObject_ASSERT_WITH_MSG(self,
Py_REFCNT(self) > 0,
"refcount is too small");
/* Undo the temporary resurrection; can't use DECREF here, it would
* cause a recursive call. */
Py_SET_REFCNT(self, Py_REFCNT(self) - 1);
if (Py_REFCNT(self) == 0) {
return 0; /* this is the normal path out */
}
/* tp_finalize 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);
_PyObject_ASSERT(self,
(!_PyType_IS_GC(Py_TYPE(self))
|| _PyObject_GC_IS_TRACKED(self)));
return -1;
}
int
PyObject_Print(PyObject *op, FILE *fp, int flags)
{
int ret = 0;
if (PyErr_CheckSignals())
return -1;
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "stack overflow");
return -1;
}
#endif
clearerr(fp); /* Clear any previous error condition */
if (op == NULL) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "");
Py_END_ALLOW_THREADS
}
else {
if (Py_REFCNT(op) <= 0) {
Py_BEGIN_ALLOW_THREADS
fprintf(fp, "", Py_REFCNT(op), (void *)op);
Py_END_ALLOW_THREADS
}
else {
PyObject *s;
if (flags & Py_PRINT_RAW)
s = PyObject_Str(op);
else
s = PyObject_Repr(op);
if (s == NULL) {
ret = -1;
}
else {
assert(PyUnicode_Check(s));
const char *t;
Py_ssize_t len;
t = PyUnicode_AsUTF8AndSize(s, &len);
if (t == NULL) {
ret = -1;
}
else {
fwrite(t, 1, len, fp);
}
Py_DECREF(s);
}
}
}
if (ret == 0) {
if (ferror(fp)) {
PyErr_SetFromErrno(PyExc_OSError);
clearerr(fp);
ret = -1;
}
}
return ret;
}
/* For debugging convenience. Set a breakpoint here and call it from your DLL */
void
_Py_BreakPoint(void)
{
}
/* Heuristic checking if the object memory is uninitialized or deallocated.
Rely on the debug hooks on Python memory allocators:
see _PyMem_IsPtrFreed().
The function can be used to prevent segmentation fault on dereferencing
pointers like 0xDDDDDDDDDDDDDDDD. */
int
_PyObject_IsFreed(PyObject *op)
{
if (_PyMem_IsPtrFreed(op) || _PyMem_IsPtrFreed(Py_TYPE(op))) {
return 1;
}
return 0;
}
/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */
void
_PyObject_Dump(PyObject* op)
{
if (_PyObject_IsFreed(op)) {
/* It seems like the object memory has been freed:
don't access it to prevent a segmentation fault. */
fprintf(stderr, "