Skip to content

Commit 992446d

Browse files
authored
GH-113462: Limit the number of versions that a single class can use. (GH-114900)
1 parent 87cd20a commit 992446d

File tree

4 files changed

+22
-1
lines changed

4 files changed

+22
-1
lines changed

Diff for: Include/cpython/object.h

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ struct _typeobject {
229229

230230
/* bitset of which type-watchers care about this type */
231231
unsigned char tp_watched;
232+
uint16_t tp_versions_used;
232233
};
233234

234235
/* This struct is used by the specializer

Diff for: Lib/test/test_type_cache.py

+13
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,19 @@ class C:
7979

8080
_clear_type_cache()
8181

82+
def test_per_class_limit(self):
83+
class C:
84+
x = 0
85+
86+
type_assign_version(C)
87+
orig_version = type_get_version(C)
88+
for i in range(1001):
89+
C.x = i
90+
type_assign_version(C)
91+
92+
new_version = type_get_version(C)
93+
self.assertEqual(new_version, 0)
94+
8295

8396
@support.cpython_only
8497
class TypeCacheWithSpecializationTests(unittest.TestCase):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Limit the number of versions that a single class can use. Prevents a few
2+
wayward classes using up all the version numbers.

Diff for: Objects/typeobject.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,8 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
908908
}
909909
}
910910

911+
#define MAX_VERSIONS_PER_CLASS 1000
912+
911913
static int
912914
assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
913915
{
@@ -922,7 +924,10 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
922924
if (!_PyType_HasFeature(type, Py_TPFLAGS_READY)) {
923925
return 0;
924926
}
925-
927+
if (type->tp_versions_used >= MAX_VERSIONS_PER_CLASS) {
928+
return 0;
929+
}
930+
type->tp_versions_used++;
926931
if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
927932
/* static types */
928933
if (NEXT_GLOBAL_VERSION_TAG > _Py_MAX_GLOBAL_TYPE_VERSION_TAG) {

0 commit comments

Comments
 (0)