10000 GH-113462: Limit the number of versions that a single class can use. … · python/cpython@992446d · GitHub
[go: up one dir, main page]

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

Include/cpython/object.h

Lines changed: 1 addition & 0 deletions
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

Lib/test/test_type_cache.py

Lines changed: 13 additions & 0 deletions
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):
Lines changed: 2 additions & 0 deletions
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.

Objects/typeobject.c

Lines changed: 6 additions & 1 deletion
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)
0