subtype_dealloc for heap types is a footgun
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 35.9k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
Bug report
Bug description:
#include <Python.h>
static PyType_Slot base_slots[] = {
{0, 0}
};
static PyType_Spec base_spec = {
.name = "Base",
.basicsize = 0,
.itemsize = 0,
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.slots = base_slots,
};
static void derived_dealloc(PyObject *o) {
// call base class dealloc
destructor base_slot = PyType_GetSlot(Py_TYPE(o), Py_tp_dealloc);
base_slot(o);
}
static PyType_Slot derived_slots[] = {
{Py_tp_dealloc, derived_dealloc},
{0, 0}
};
static PyType_Spec derived_spec = {
.name = "Derived",
.basicsize = 0,
.itemsize = 0,
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.slots = derived_slots,
};
static int
deallocdemo_module_exec(PyObject *m)
{
PyObject *base_type = PyType_FromModuleAndSpec(
m,
&base_spec,
NULL
);
if (!base_type) return -1;
if (PyModule_AddObjectRef(m, "Base", base_type) < 0) {
Py_DECREF(base_type);
return -1;
}
PyObject *derived_type = PyType_FromModuleAndSpec(
m,
&derived_spec,
base_type
);
Py_DECREF(base_type);
if (!derived_type) return -1;
int add_object_res = PyModule_AddObjectRef(m, "Derived", derived_type);
Py_DECREF(derived_type);
return add_object_res;
}
static PyModuleDef_Slot deallocdemo_module_slots[] = {
{Py_mod_exec, deallocdemo_module_exec},
{0, NULL}
};
static struct PyModuleDef deallocdemo_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "deallocdemo",
.m_size = 0,
.m_slots = deallocdemo_module_slots,
};
PyMODINIT_FUNC
PyInit_deallocdemo(void)
{
return PyModuleDef_Init(&deallocdemo_module);
}
Essentially, subtype_dealloc prevents any derived type from implementing its own dealloc function. In the example above, trying to destroy a Derived object will cause an infinite loop because subtype_dealloc will call derived_dealloc (which calls subtype_dealloc).
This is something that works better for static-types, where the default was to inherit the tp_dealloc of the base class. I appreciate heap types are a little more complex in the inheritance they allow though.
I suspect this is now too late to change easily, and I can't personally think of any obvious solutions to it. It's obvious possible to work around (by creating a custom tp_dealloc at all levels) so the issue is more "it's a footgun" than "it's unworkable". But it seems worth raising the issue in case it can be improved somehow.
CPython versions tested on:
3.13
Operating systems tested on:
Linux
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Reproducer sử dụng PyType_FromModuleAndSpec, PyType_GetSlot, Py_tp_dealloc và subtype_dealloc; hãy bắt đầu bằng cách lần theo đường dẫn giải phân bổ đó trong phần triển khai kiểu của CPython. Xác lập và kiểm thử hành vi an toàn cho các bộ giải phân bổ của kiểu heap bằng cách sử dụng extension Base/Derived được cung cấp làm trường hợp hồi quy; issue không nêu tên tệp kiểm thử và cũng không quy định giải pháp.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- c, python
- Lĩnh vực
- backend-api-design
- Loại issue
- Lỗi
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Cần làm rõ
- Mức phù hợp với người mới
- 30/100