-
-
Notifications
You must be signed in to change notification settings - Fork 35k
bpo-45385: Fix reference leak from descr_check #28719
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Fix reference leak from descr_check. Patch by Dong-hee Na. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,22 +72,16 @@ wrapperdescr_repr(PyWrapperDescrObject *descr) | |
| } | ||
|
|
||
| static int | ||
| descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres) | ||
| descr_check(PyDescrObject *descr, PyObject *obj) | ||
| { | ||
| if (obj == NULL) { | ||
| Py_INCREF(descr); | ||
| *pres = (PyObject *)descr; | ||
| return 1; | ||
| } | ||
| if (!PyObject_TypeCheck(obj, descr->d_type)) { | ||
| PyErr_Format(PyExc_TypeError, | ||
| "descriptor '%V' for '%.100s' objects " | ||
| "doesn't apply to a '%.100s' object", | ||
| descr_name((PyDescrObject *)descr), "?", | ||
| descr->d_type->tp_name, | ||
| Py_TYPE(obj)->tp_name); | ||
| *pres = NULL; | ||
| return 1; | ||
| return -1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
@@ -137,10 +131,12 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) | |
| static PyObject * | ||
| method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) | ||
| { | ||
| PyObject *res; | ||
|
|
||
| if (descr_check((PyDescrObject *)descr, obj, &res)) | ||
| return res; | ||
| if (obj == NULL) { | ||
| return Py_NewRef(descr); | ||
| } | ||
| if (descr_check((PyDescrObject *)descr, obj) < 0) { | ||
| return NULL; | ||
| } | ||
| if (descr->d_method->ml_flags & METH_METHOD) { | ||
| if (PyType_Check(type)) { | ||
| return PyCMethod_New(descr->d_method, obj, NULL, descr->d_common.d_type); | ||
|
|
@@ -159,10 +155,12 @@ method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) | |
| static PyObject * | ||
| member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) | ||
| { | ||
| PyObject *res; | ||
|
|
||
| if (descr_check((PyDescrObject *)descr, obj, &res)) | ||
| return res; | ||
| if (obj == NULL) { | ||
| return Py_NewRef(descr); | ||
| } | ||
| if (descr_check((PyDescrObject *)descr, obj) < 0) { | ||
| return NULL; | ||
| } | ||
|
|
||
| if (descr->d_member->flags & PY_AUDIT_READ) { | ||
| if (PySys_Audit("object.__getattr__", "Os", | ||
|
|
@@ -177,10 +175,12 @@ member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) | |
| static PyObject * | ||
| getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) | ||
| { | ||
| PyObject *res; | ||
|
|
||
| if (descr_check((PyDescrObject *)descr, obj, &res)) | ||
| return res; | ||
| if (obj == NULL) { | ||
| return Py_NewRef(descr); | ||
| } | ||
| if (descr_check((PyDescrObject *)descr, obj) < 0) { | ||
| return NULL; | ||
| } | ||
| if (descr->d_getset->get != NULL) | ||
| return descr->d_getset->get(obj, descr->d_getset->closure); | ||
| PyErr_Format(PyExc_AttributeError, | ||
|
|
@@ -193,16 +193,17 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) | |
| static PyObject * | ||
| wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type) | ||
| { | ||
| PyObject *res; | ||
|
|
||
| if (descr_check((PyDescrObject *)descr, obj, &res)) | ||
| return res; | ||
| if (obj == NULL) { | ||
| return Py_NewRef(descr); | ||
| } | ||
| if (descr_check((PyDescrObject *)descr, obj) < 0) { | ||
| return NULL; | ||
| } | ||
| return PyWrapper_New((PyObject *)descr, obj); | ||
| } | ||
|
|
||
| static int | ||
| descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, why did this (and the code below) change too? I don't think this was buggy, though the new code improves readability/makes it easier to understand. I'm guessing for consistency reasons?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I asked @corona10 to mention compiler warnings in the commit message. I cannot see compiler warnings in https://bugs.python.org/issue45385, in the PR description, or in the commit message.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes and it improve the readability :) |
||
| int *pres) | ||
| descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value) | ||
| { | ||
| assert(obj != NULL); | ||
| if (!PyObject_TypeCheck(obj, descr->d_type)) { | ||
|
|
@@ -212,32 +213,30 @@ descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value, | |
| descr_name(descr), "?", | ||
| descr->d_type->tp_name, | ||
| Py_TYPE(obj)->tp_name); | ||
| *pres = -1; | ||
| return 1; | ||
| return -1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| static int | ||
| member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) | ||
| { | ||
| int res; | ||
|
|
||
| if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) | ||
| return res; | ||
| if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { | ||
| return -1; | ||
| } | ||
| return PyMember_SetOne((char *)obj, descr->d_member, value); | ||
| } | ||
|
|
||
| static int | ||
| getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) | ||
| { | ||
| int res; | ||
|
|
||
| if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) | ||
| return res; | ||
| if (descr->d_getset->set != NULL) | ||
| if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { | ||
| return -1; | ||
| } | ||
| if (descr->d_getset->set != NULL) { | ||
| return descr->d_getset->set(obj, value, | ||
| descr->d_getset->closure); | ||
| } | ||
| PyErr_Format(PyExc_AttributeError, | ||
| "attribute '%V' of '%.100s' objects is not writable", | ||
| descr_name((PyDescrObject *)descr), "?", | ||
|
|
@@ -264,8 +263,7 @@ method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObj | |
| return -1; | ||
| } | ||
| PyObject *self = args[0]; | ||
| PyObject *dummy; | ||
| if (descr_check((PyDescrObject *)func, self, &dummy)) { | ||
| if (descr_check((PyDescrObject *)func, self) < 0) { | ||
| return -1; | ||
| } | ||
| if (kwnames && PyTuple_GET_SIZE(kwnames)) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.