Skip to content

Commit 3cae16d

Browse files
bpo-35444: Fix error handling when fail to look up builtin "getattr". (GH-11047) (GH-11107)
(cherry picked from commit bb86bf4)
1 parent 62674f3 commit 3cae16d

File tree

7 files changed

+29
-30
lines changed

7 files changed

+29
-30
lines changed

‎Include/ceval.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void);
4848
PyAPI_FUNC(PyObject *) PyEval_GetLocals(void);
4949
PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void);
5050

51+
#ifndef Py_LIMITED_API
52+
/* Helper to look up a builtin object */
53+
PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *);
5154
/* Look at the current frame's (if any) code's co_flags, and turn on
5255
the corresponding compiler flags in cf->cf_flags. Return 1 if any
5356
flag was set, else return 0. */
54-
#ifndef Py_LIMITED_API
5557
PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
5658
#endif
5759

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed error handling in pickling methods when fail to look up builtin
2+
"getattr".

‎Modules/_pickle.c‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,19 +207,15 @@ _Pickle_ClearState(PickleState *st)
207207
static int
208208
_Pickle_InitState(PickleState *st)
209209
{
210-
PyObject *builtins;
211210
PyObject *copyreg = NULL;
212211
PyObject *compat_pickle = NULL;
213212
PyObject *codecs = NULL;
214213
PyObject *functools = NULL;
214+
_Py_IDENTIFIER(getattr);
215215

216-
builtins = PyEval_GetBuiltins();
217-
if (builtins == NULL)
218-
goto error;
219-
st->getattr = PyDict_GetItemString(builtins, "getattr");
216+
st->getattr = _PyEval_GetBuiltinId(&PyId_getattr);
220217
if (st->getattr == NULL)
221218
goto error;
222-
Py_INCREF(st->getattr);
223219

224220
copyreg = PyImport_ImportModule("copyreg");
225221
if (!copyreg)

‎Objects/classobject.c‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,15 @@ method_reduce(PyMethodObject *im)
7777
{
7878
PyObject *self = PyMethod_GET_SELF(im);
7979
PyObject *func = PyMethod_GET_FUNCTION(im);
80-
PyObject *builtins;
81-
PyObject *getattr;
8280
PyObject *funcname;
8381
_Py_IDENTIFIER(getattr);
8482

8583
funcname = _PyObject_GetAttrId(func, &PyId___name__);
8684
if (funcname == NULL) {
8785
return NULL;
8886
}
89-
builtins = PyEval_GetBuiltins();
90-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
91-
return Py_BuildValue("O(ON)", getattr, self, funcname);
87+
return Py_BuildValue("N(ON)", _PyEval_GetBuiltinId(&PyId_getattr),
88+
self, funcname);
9289
}
9390

9491
static PyMethodDef method_methods[] = {

‎Objects/descrobject.c‎

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -450,14 +450,9 @@ descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
450450
static PyObject *
451451
descr_reduce(PyDescrObject *descr)
452452
{
453-
PyObject *builtins;
454-
PyObject *getattr;
455453
_Py_IDENTIFIER(getattr);
456-
457-
builtins = PyEval_GetBuiltins();
458-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
459-
return Py_BuildValue("O(OO)", getattr, PyDescr_TYPE(descr),
460-
PyDescr_NAME(descr));
454+
return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
455+
PyDescr_TYPE(descr), PyDescr_NAME(descr));
461456
}
462457

463458
static PyMethodDef descr_methods[] = {
@@ -1088,13 +1083,9 @@ wrapper_repr(wrapperobject *wp)
10881083
static PyObject *
10891084
wrapper_reduce(wrapperobject *wp)
10901085
{
1091-
PyObject *builtins;
1092-
PyObject *getattr;
10931086
_Py_IDENTIFIER(getattr);
1094-
1095-
builtins = PyEval_GetBuiltins();
1096-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
1097-
return Py_BuildValue("O(OO)", getattr, wp->self, PyDescr_NAME(wp->descr));
1087+
return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1088+
wp->self, PyDescr_NAME(wp->descr));
10981089
}
10991090

11001091
static PyMethodDef wrapper_methods[] = {

‎Objects/methodobject.c‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,13 @@ meth_dealloc(PyCFunctionObject *m)
103103
static PyObject *
104104
meth_reduce(PyCFunctionObject *m)
105105
{
106-
PyObject *builtins;
107-
PyObject *getattr;
108106
_Py_IDENTIFIER(getattr);
109107

110108
if (m->m_self == NULL || PyModule_Check(m->m_self))
111109
return PyUnicode_FromString(m->m_ml->ml_name);
112110

113-
builtins = PyEval_GetBuiltins();
114-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
115-
return Py_BuildValue("O(Os)", getattr, m->m_self, m->m_ml->ml_name);
111+
return Py_BuildValue("N(Os)", _PyEval_GetBuiltinId(&PyId_getattr),
112+
m->m_self, m->m_ml->ml_name);
116113
}
117114

118115
static PyMethodDef meth_methods[] = {

‎Python/ceval.c‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4419,6 +4419,20 @@ PyEval_GetBuiltins(void)
44194419
return current_frame->f_builtins;
44204420
}
44214421

4422+
/* Convenience function to get a builtin from its name */
4423+
PyObject *
4424+
_PyEval_GetBuiltinId(_Py_Identifier *name)
4425+
{
4426+
PyObject *attr = _PyDict_GetItemIdWithError(PyEval_GetBuiltins(), name);
4427+
if (attr) {
4428+
Py_INCREF(attr);
4429+
}
4430+
else if (!PyErr_Occurred()) {
4431+
PyErr_SetObject(PyExc_AttributeError, _PyUnicode_FromId(name));
4432+
}
4433+
return attr;
4434+
}
4435+
44224436
PyObject *
44234437
PyEval_GetLocals(void)
44244438
{

0 commit comments

Comments
 (0)