summaryrefslogtreecommitdiffstats
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2024-10-17 16:45:25 (GMT)
committerGitHub <noreply@github.com>2024-10-17 16:45:25 (GMT)
commitf203d1cb52f7697140337a73841c8412282e2ee0 (patch)
tree4f78e4c4c8f9a0d7ce7e8dc1a242cbe7f1b57f04 /Objects/funcobject.c
parent04d6dd23e2d8a3132772cf7ce928676e26313585 (diff)
downloadcpython-f203d1cb52f7697140337a73841c8412282e2ee0.zip
cpython-f203d1cb52f7697140337a73841c8412282e2ee0.tar.gz
cpython-f203d1cb52f7697140337a73841c8412282e2ee0.tar.bz2
gh-125017: Fix crash on premature access to classmethod/staticmethod annotations (#125636)
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r--Objects/funcobject.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 6119a96..f86ef32 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -1220,30 +1220,43 @@ functools_wraps(PyObject *wrapper, PyObject *wrapped)
// Used for wrapping __annotations__ and __annotate__ on classmethod
// and staticmethod objects.
static PyObject *
-descriptor_get_wrapped_attribute(PyObject *wrapped, PyObject *dict, PyObject *name)
+descriptor_get_wrapped_attribute(PyObject *wrapped, PyObject *obj, PyObject *name)
{
+ PyObject *dict = PyObject_GenericGetDict(obj, NULL);
+ if (dict == NULL) {
+ return NULL;
+ }
PyObject *res;
if (PyDict_GetItemRef(dict, name, &res) < 0) {
+ Py_DECREF(dict);
return NULL;
}
if (res != NULL) {
+ Py_DECREF(dict);
return res;
}
res = PyObject_GetAttr(wrapped, name);
if (res == NULL) {
+ Py_DECREF(dict);
return NULL;
}
if (PyDict_SetItem(dict, name, res) < 0) {
+ Py_DECREF(dict);
Py_DECREF(res);
return NULL;
}
+ Py_DECREF(dict);
return res;
}
static int
-descriptor_set_wrapped_attribute(PyObject *dict, PyObject *name, PyObject *value,
+descriptor_set_wrapped_attribute(PyObject *oobj, PyObject *name, PyObject *value,
char *type_name)
{
+ PyObject *dict = PyObject_GenericGetDict(oobj, NULL);
+ if (dict == NULL) {
+ return -1;
+ }
if (value == NULL) {
if (PyDict_DelItem(dict, name) < 0) {
if (PyErr_ExceptionMatches(PyExc_KeyError)) {
@@ -1251,14 +1264,18 @@ descriptor_set_wrapped_attribute(PyObject *dict, PyObject *name, PyObject *value
PyErr_Format(PyExc_AttributeError,
"'%.200s' object has no attribute '%U'",
type_name, name);
+ return -1;
}
else {
+ Py_DECREF(dict);
return -1;
}
}
+ Py_DECREF(dict);
return 0;
}
else {
+ Py_DECREF(dict);
return PyDict_SetItem(dict, name, value);
}
}
@@ -1380,28 +1397,26 @@ static PyObject *
cm_get___annotations__(PyObject *self, void *closure)
{
classmethod *cm = _PyClassMethod_CAST(self);
- return descriptor_get_wrapped_attribute(cm->cm_callable, cm->cm_dict, &_Py_ID(__annotations__));
+ return descriptor_get_wrapped_attribute(cm->cm_callable, self, &_Py_ID(__annotations__));
}
static int
cm_set___annotations__(PyObject *self, PyObject *value, void *closure)
{
- classmethod *cm = _PyClassMethod_CAST(self);
- return descriptor_set_wrapped_attribute(cm->cm_dict, &_Py_ID(__annotations__), value, "classmethod");
+ return descriptor_set_wrapped_attribute(self, &_Py_ID(__annotations__), value, "classmethod");
}
static PyObject *
cm_get___annotate__(PyObject *self, void *closure)
{
classmethod *cm = _PyClassMethod_CAST(self);
- return descriptor_get_wrapped_attribute(cm->cm_callable, cm->cm_dict, &_Py_ID(__annotate__));
+ return descriptor_get_wrapped_attribute(cm->cm_callable, self, &_Py_ID(__annotate__));
}
static int
cm_set___annotate__(PyObject *self, PyObject *value, void *closure)
{
- classmethod *cm = _PyClassMethod_CAST(self);
- return descriptor_set_wrapped_attribute(cm->cm_dict, &_Py_ID(__annotate__), value, "classmethod");
+ return descriptor_set_wrapped_attribute(self, &_Py_ID(__annotate__), value, "classmethod");
}
@@ -1615,28 +1630,26 @@ static PyObject *
sm_get___annotations__(PyObject *self, void *closure)
{
staticmethod *sm = _PyStaticMethod_CAST(self);
- return descriptor_get_wrapped_attribute(sm->sm_callable, sm->sm_dict, &_Py_ID(__annotations__));
+ return descriptor_get_wrapped_attribute(sm->sm_callable, self, &_Py_ID(__annotations__));
}
static int
sm_set___annotations__(PyObject *self, PyObject *value, void *closure)
{
- staticmethod *sm = _PyStaticMethod_CAST(self);
- return descriptor_set_wrapped_attribute(sm->sm_dict, &_Py_ID(__annotations__), value, "staticmethod");
+ return descriptor_set_wrapped_attribute(self, &_Py_ID(__annotations__), value, "staticmethod");
}
static PyObject *
sm_get___annotate__(PyObject *self, void *closure)
{
staticmethod *sm = _PyStaticMethod_CAST(self);
- return descriptor_get_wrapped_attribute(sm->sm_callable, sm->sm_dict, &_Py_ID(__annotate__));
+ return descriptor_get_wrapped_attribute(sm->sm_callable, self, &_Py_ID(__annotate__));
}
static int
sm_set___annotate__(PyObject *self, PyObject *value, void *closure)
{
- staticmethod *sm = _PyStaticMethod_CAST(self);
- return descriptor_set_wrapped_attribute(sm->sm_dict, &_Py_ID(__annotate__), value, "staticmethod");
+ return descriptor_set_wrapped_attribute(self, &_Py_ID(__annotate__), value, "staticmethod");
}
static PyGetSetDef sm_getsetlist[] = {