8000 gh-120161: Fix a Crash in the _datetime Module by ericsnowcurrently · Pull Request #120182 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-120161: Fix a Crash in the _datetime Module #120182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add _PyTypes_FiniExtTypes().
  • Loading branch information
ericsnowcurrently committed Jun 6, 2024
commit 0054962fda3b3a6f06d3c8a5a8289a29d2f0fbb9
20 changes: 15 additions & 5 deletions Include/internal/pycore_typeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,25 @@ extern "C" {
#define _Py_TYPE_BASE_VERSION_TAG (2<<16)
#define _Py_MAX_GLOBAL_TYPE_VERSION_TAG (_Py_TYPE_BASE_VERSION_TAG - 1)

/* For now we hard-code this to a value for which we are confident
all the static builtin types will fit (for all builds). */
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 200
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10
#define _Py_MAX_MANAGED_STATIC_TYPES \
(_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES + _Py_MAX_MANAGED_STATIC_EXT_TYPES)

struct _types_runtime_state {
/* Used to set PyTypeObject.tp_version_tag for core static types. */
// bpo-42745: next_version_tag remains shared by all interpreters
// because of static types.
unsigned int next_version_tag;

struct {
struct {
PyTypeObject *type;
int64_t interp_count;
} types[_Py_MAX_MANAGED_STATIC_TYPES];
} managed_static;
};


Expand All @@ -42,11 +56,6 @@ struct type_cache {
struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP];
};

/* For now we hard-code this to a value for which we are confident
all the static builtin types will fit (for all builds). */
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 200
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10

typedef struct {
PyTypeObject *type;
int isbuiltin;
Expand Down Expand Up @@ -125,6 +134,7 @@ struct types_state {

extern PyStatus _PyTypes_InitTypes(PyInterpreterState *);
extern void _PyTypes_FiniTypes(PyInterpreterState *);
extern void _PyTypes_FiniExtTypes(PyInterpreterState *interp);
extern void _PyTypes_Fini(PyInterpreterState *);
extern void _PyTypes_AfterFork(void);

Expand Down
81 changes: 78 additions & 3 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,30 @@ managed_static_type_index_clear(PyTypeObject *self)
self->tp_subclasses = NULL;
}

static PyTypeObject *
static_ext_type_lookup(PyInterpreterState *interp, size_t index,
int64_t *p_interp_count)
{
assert(interp->runtime == &_PyRuntime);
assert(index < _Py_MAX_MANAGED_STATIC_EXT_TYPES);

size_t full_index = index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES;
int64_t interp_count =
_PyRuntime.types.managed_static.types[full_index].interp_count;
assert((interp_count == 0) ==
(_PyRuntime.types.managed_static.types[full_index].type == NULL));
*p_interp_count = interp_count;

PyTypeObject *type = interp->types.for_extensions.initialized[index].type;
if (type == NULL) {
return NULL;
}
assert(!interp->types.for_extensions.initialized[index].isbuiltin);
assert(type == _PyRuntime.types.managed_static.types[full_index].type);
assert(managed_static_type_index_is_set(type));
return type;
}

static inline managed_static_type_state *
static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self)
{
Expand Down Expand Up @@ -202,6 +226,8 @@ static void
managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
int isbuiltin, int initial)
{
assert(interp->runtime == &_PyRuntime);

size_t index;
if (initial) {
assert(!managed_static_type_index_is_set(self));
Expand All @@ -228,6 +254,21 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
assert(index < _Py_MAX_MANAGED_STATIC_EXT_TYPES);
}
}
size_t full_index = isbuiltin
? index
: index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES;

assert((initial == 1) ==
(_PyRuntime.types.managed_static.types[full_index].interp_count == 0));
_PyRuntime.types.managed_static.types[full_index].interp_count += 1;

if (initial) {
assert(_PyRuntime.types.managed_static.types[full_index].type == NULL);
_PyRuntime.types.managed_static.types[full_index].type = self;
}
else {
assert(_PyRuntime.types.managed_static.types[full_index].type == self);
}

managed_static_type_state *state = isbuiltin
? &(interp->types.builtins.initialized[index])
Expand Down Expand Up @@ -256,15 +297,28 @@ static void
managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
int isbuiltin, int final)
{
size_t index = managed_static_type_index_get(self);
size_t full_index = isbuiltin
? index
: index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES;

managed_static_type_state *state = isbuiltin
? static_builtin_state_get(interp, self)
: static_ext_type_state_get(interp, self);
? &(interp->types.builtins.initialized[index])
: &(interp->types.for_extensions.initialized[index]);
assert(state != NULL);

assert(_PyRuntime.types.managed_static.types[full_index].interp_count > 0);
assert(_PyRuntime.types.managed_static.types[full_index].type == state->type);

assert(state->type != NULL);
state->type = NULL;
assert(state->tp_weaklist == NULL); // It was already cleared out.

_PyRuntime.types.managed_static.types[full_index].interp_count -= 1;
if (final) {
assert(!_PyRuntime.types.managed_static.types[full_index].interp_count);
_PyRuntime.types.managed_static.types[full_index].type = NULL;

managed_static_type_index_clear(self);
}

Expand Down Expand Up @@ -840,8 +894,12 @@ _PyTypes_Fini(PyInterpreterState *interp)
struct type_cache *cache = &interp->types.type_cache;
type_cache_clear(cache, NULL);

// All the managed static types should have been finalized already.
assert(interp->types.for_extensions.num_initialized == 0);
for (size_t i = 0; i < _Py_MAX_MANAGED_STATIC_EXT_TYPES; i++) {
assert(interp->types.for_extensions.initialized[i].type == NULL);
}
assert(interp->types.builtins.num_initialized == 0);
// All the static builtin types should have been finalized already.
for (size_t i = 0; i < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; i++) {
assert(interp->types.builtins.initialized[i].type == NULL);
}
Expand Down Expand Up @@ -5782,6 +5840,23 @@ _PyStaticType_FiniForExtension(PyInterpreterState *interp, PyTypeObject *type, i
fini_static_type(interp, type, 0, final);
}

void
_PyTypes_FiniExtTypes(PyInterpreterState *interp)
{
for (size_t i = _Py_MAX_MANAGED_STATIC_EXT_TYPES; i > 0; i--) {
if (interp->types.for_extensions.num_initialized == 0) {
break;
}
int64_t count = 0;
PyT B20E ypeObject *type = static_ext_type_lookup(interp, i-1, &count);
if (type == NULL) {
continue;
}
int final = (count == 1);
fini_static_type(interp, type, 0, final);
}
}

void
_PyStaticType_FiniBuiltin(PyInterpreterState *interp, PyTypeObject *type)
{
Expand Down
1 change: 1 addition & 0 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,7 @@ flush_std_files(void)
static void
finalize_interp_types(PyInterpreterState *interp)
{
_PyTypes_FiniExtTypes(interp);
_PyUnicode_FiniTypes(interp);
_PySys_FiniTypes(interp);
_PyXI_FiniTypes(interp);
Expand Down
0